लगता है पसंदीदा तरीका
मैं इस धारणा के तहत था कि निम्नलिखित का परीक्षण पहले से ही दूसरों द्वारा किया गया था, विशेष रूप से कुछ टिप्पणियों के आधार पर। लेकिन मेरे परीक्षण से पता चलता है कि ये दो विधियां वास्तव में DB स्तर पर काम करती हैं, यहां तक कि .NET के माध्यम से कनेक्ट होने पर भी SqlClient
। इनका परीक्षण और सत्यापन अन्यों द्वारा किया गया है।
सर्वर चौड़ा
आप उपयोगकर्ता विकल्प सर्वर कॉन्फ़िगरेशन सेटिंग को सेट कर सकते हैं जो कि वर्तमान में OR
64 -बिट (मूल्य के लिए ARITHABORT
) के साथ बिट-वार एड है । यदि आप बिट-वार या ( |
) का उपयोग नहीं करते हैं, लेकिन इसके बजाय एक सीधा असाइनमेंट ( =
) करते हैं तो आप किसी भी अन्य मौजूदा विकल्प को मिटा देंगे।
DECLARE @Value INT;
SELECT @Value = CONVERT(INT, [value_in_use]) --[config_value] | 64
FROM sys.configurations sc
WHERE sc.[name] = N'user options';
IF ((@Value & 64) <> 64)
BEGIN
PRINT 'Enabling ARITHABORT...';
SET @Value = (@Value | 64);
EXEC sp_configure N'user options', @Value;
RECONFIGURE;
END;
EXEC sp_configure N'user options'; -- verify current state
डाटाबेस स्तरीय
इसे प्रति डेटाबेस सेट के माध्यम से प्रति-डेटाबेस सेट किया जा सकता है :
USE [master];
IF (EXISTS(
SELECT *
FROM sys.databases db
WHERE db.[name] = N'{database_name}'
AND db.[is_arithabort_on] = 0
))
BEGIN
PRINT 'Enabling ARITHABORT...';
ALTER DATABASE [{database_name}] SET ARITHABORT ON WITH NO_WAIT;
END;
वैकल्पिक दृष्टिकोण
नहीं-तो-अच्छी खबर यह है कि मैंने इस विषय पर बहुत सारी खोज की है, केवल यह पता लगाने के लिए कि बहुत से अन्य लोगों ने इस विषय पर बहुत सारी खोज की है, और व्यवहार को कॉन्फ़िगर करने का कोई तरीका नहीं है। का है SqlClient
। कुछ MSDN दस्तावेज़ीकरण का अर्थ है कि यह एक ConnectionString के माध्यम से किया जा सकता है, लेकिन ऐसे कोई कीवर्ड नहीं हैं जो इन सेटिंग्स को बदलने की अनुमति देंगे। एक अन्य दस्तावेज़ का अर्थ है कि इसे क्लाइंट नेटवर्क कॉन्फ़िगरेशन / कॉन्फ़िगरेशन प्रबंधक के माध्यम से बदला जा सकता है, लेकिन यह संभव भी नहीं लगता है। इसलिए, और दुर्भाग्य से, आपको SET ARITHABORT ON;
मैन्युअल रूप से निष्पादित करने की आवश्यकता होगी । विचार करने के कुछ तरीके इस प्रकार हैं:
यदि आप एंटिटी फ्रेमवर्क 6 (या नए) का उपयोग कर रहे हैं, तो आप या तो कोशिश कर सकते हैं:
Database.ExecuteSqlCommand का उपयोग करें : context.Database.ExecuteSqlCommand("SET ARITHABORT ON;");
आदर्श रूप से यह DB कनेक्शन खोलने के बाद एक बार निष्पादित किया जाएगा, और प्रत्येक क्वेरी के लिए नहीं।
या तो एक इंटरसेप्टर बनाएं :
यह निष्पादित होने से पहले आपको एसक्यूएल को संशोधित करने की अनुमति देगा, जिस स्थिति में आप बस इसके साथ उपसर्ग कर सकते हैं SET ARITHABORT ON;
:। यहां नकारात्मक पक्ष यह है कि यह प्रत्येक क्वेरी के अनुसार होगा, जब तक कि आप स्थानीय चर को स्टोर नहीं करते हैं या नहीं, इस स्थिति को पकड़ने के लिए निष्पादित किया गया है या नहीं और उस समय के लिए परीक्षण करें (जो वास्तव में इतना अतिरिक्त काम नहीं है, लेकिन इसका उपयोग करना ExecuteSqlCommand
है) शायद आसान)।
उनमें से कोई भी आपको किसी मौजूदा कोड को बदलने के बिना एक स्थान पर इसे संभालने की अनुमति देगा।
ईएलएसई , आप एक आवरण विधि बना सकते हैं जो ऐसा करती है:
public static SqlDataReader ExecuteReaderWithSetting(SqlCommand CommandToExec)
{
CommandToExec.CommandText = "SET ARITHABORT ON;\n" + CommandToExec.CommandText;
return CommandToExec.ExecuteReader();
}
और फिर वर्तमान _Reader = _Command.ExecuteReader();
संदर्भों को बदल दें _Reader = ExecuteReaderWithSetting(_Command);
।
ऐसा करने से सेटिंग को केवल एक स्थान पर नियंत्रित करने की अनुमति मिलती है, जबकि केवल न्यूनतम और सरलीकृत कोड परिवर्तनों की आवश्यकता होती है जो कि ज्यादातर फाइंड एंड रिप्लेसमेंट के माध्यम से किए जा सकते हैं।
अभी तक बेहतर ( वरना भाग 2), के बाद से इस एक कनेक्शन स्तर सेटिंग है, यह प्रत्येक SqlCommand.Execute __ () प्रति कॉल निष्पादित करने की जरूरत नहीं है। इसलिए के लिए एक आवरण बनाने के बजाय ExecuteReader()
, के लिए एक आवरण बनाएँ Connection.Open()
:
public static void OpenAndSetArithAbort(SqlConnection MyConnection)
{
using (SqlCommand _Command = MyConnection.CreateCommand())
{
_Command.CommandType = CommandType.Text;
_Command.CommandText = "SET ARITHABORT ON;";
MyConnection.Open();
_Command.ExecuteNonQuery();
}
return;
}
और फिर मौजूदा _Connection.Open();
संदर्भों को प्रतिस्थापित करें OpenAndSetArithAbort(_Connection);
।
उपरोक्त दोनों विचारों को एक वर्ग बनाकर अधिक OO शैली में लागू किया जा सकता है जो SqlCommand या SqlConnection तक फैला हुआ है।
या बेहतर अभी तक ( वरना भाग 3), आप कनेक्शन StateChange के लिए एक ईवेंट हैंडलर बनाने और इसे गुण सेट कर सकते हैं जब से कनेक्शन परिवर्तन Closed
करने के लिए Open
इस प्रकार है:
protected static void OnStateChange(object sender, StateChangeEventArgs args)
{
if (args.OriginalState == ConnectionState.Closed
&& args.CurrentState == ConnectionState.Open)
{
using (SqlCommand _Command = ((SqlConnection)sender).CreateCommand())
{
_Command.CommandType = CommandType.Text;
_Command.CommandText = "SET ARITHABORT ON;";
_Command.ExecuteNonQuery();
}
}
}
उस जगह के साथ, आपको केवल प्रत्येक स्थान पर निम्नलिखित को जोड़ना होगा जहां आप एक SqlConnection
उदाहरण बनाते हैं :
_Connection.StateChange += new StateChangeEventHandler(OnStateChange);
मौजूदा कोड में किसी बदलाव की जरूरत नहीं है। मैंने अभी इस विधि को एक छोटे कंसोल ऐप में आज़माया है, जिसके परिणाम को प्रिंट करके परीक्षण किया गया है SELECT SESSIONPROPERTY('ARITHABORT');
। यह वापस आ जाता है 1
, लेकिन अगर मैं ईवेंट हैंडलर को अक्षम करता हूं, तो यह वापस आ जाता है 0
।
पूर्णता की खातिर, यहां कुछ चीजें हैं जो काम नहीं करती हैं (या तो बिल्कुल भी या प्रभावी रूप से नहीं):
- लोगोन ट्रिगर : ट्रिगर, एक ही सत्र में चलने के दौरान, और भले ही स्पष्ट रूप से शुरू किए गए लेनदेन के भीतर चल रहा हो, फिर भी एक उप-प्रक्रिया है और इसलिए इसकी सेटिंग्स (
SET
कमांड, स्थानीय अस्थायी टेबल, आदि) इसके लिए स्थानीय हैं और जीवित नहीं हैं उस उप-प्रक्रिया का अंत।
SET ARITHABORT ON;
प्रत्येक संग्रहीत कार्यविधि की शुरुआत में जोड़ना :
- इसके लिए मौजूदा परियोजनाओं के लिए बहुत काम करने की आवश्यकता है, खासकर जब संग्रहीत प्रक्रियाओं की संख्या बढ़ जाती है
- यह तदर्थ प्रश्नों की मदद नहीं करता है