Görünüşe göre tercih edilen yaklaşım
Aşağıdakilerin, özellikle yorumların bazılarına dayanarak başkaları tarafından test edildiği izlenimi altındaydım. Ancak testlerim, bu iki yöntemin aslında .NET üzerinden bağlanırken bile DB düzeyinde çalıştığını gösteriyor SqlClient
. Bunlar başkaları tarafından test edilmiş ve doğrulanmıştır.
Sunucu çapında
Ayarlayabilirsiniz kullanıcı seçenekleri o bit çapında şu anda ne olursa olsun olmak sunucu yapılandırma ayarını OR
64 (değeri ile ed ARITHABORT
). Bit bilge VEYA ( |
) kullanmazsanız bunun yerine düz bir atama ( =
) yaparsanız, zaten etkin olan diğer mevcut seçenekleri silersiniz.
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
Veritabanı düzeyinde
Bu ALTER DATABASE SET ile veri tabanı başına ayarlanabilir :
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;
Alternatif yaklaşımlar
Çok iyi olmayan bir haber, bu konuyla ilgili çok fazla araştırma yaptığım, yalnızca yıllar içinde birçok kişinin bu konuda çok fazla araştırma yaptıklarını ve bu davranışı yapılandırmanın mümkün olmadığını bulmak. arasında SqlClient
. Bazı MSDN belgeleri, bir ConnectionString yoluyla yapılabileceğini belirtir, ancak bu ayarların değiştirilmesine izin verecek hiçbir Anahtar Kelime yoktur. Başka bir belge, İstemci Ağ Yapılandırması / Yapılandırma Yöneticisi aracılığıyla değiştirilebileceğini ancak bunun da mümkün görünmediğini belirtir. Dolayısıyla, ne yazık ki, SET ARITHABORT ON;
elle çalıştırmanız gerekecektir . İşte göz önünde bulundurmanız gereken bazı yollar:
EĞER sen Varlık Framework 6 (veya daha yeni) kullanıyorsanız, ya deneyebilirsiniz:
Database.ExecuteSqlCommandcontext.Database.ExecuteSqlCommand("SET ARITHABORT ON;");
komutunu kullanın : İdeal olarak, DB bağlantısı açıldıktan sonra her sorgu için değil, bir kez çalıştırılabilir.
Aşağıdakilerden birini kullanarak bir önleyici oluşturun :
Bu basitçe, öneki olabilir ki bu durumda buna çalıştırılmadan önce SQL, değiştirmelerine olanak tanır: SET ARITHABORT ON;
. Buradaki dezavantajı, her seferinde gerçekleştirilip gerçekleştirilmediğinin durumunu tespit etmek için yerel bir değişken kaydetmediğiniz sürece her sorgu başına geleceğidir (her seferinde bunun için sınamak (bu gerçekten fazladan bir iş değildir, ancak kullanmaktır ExecuteSqlCommand
). muhtemelen daha kolay).
Bunlardan biri, varolan herhangi bir kodu değiştirmeden, bunu bir noktada ele almanıza izin verecektir.
ELSE , şuna benzer , bunu yapan bir sarmalayıcı yöntemi oluşturabilirsiniz:
public static SqlDataReader ExecuteReaderWithSetting(SqlCommand CommandToExec)
{
CommandToExec.CommandText = "SET ARITHABORT ON;\n" + CommandToExec.CommandText;
return CommandToExec.ExecuteReader();
}
ve sonra sadece mevcut _Reader = _Command.ExecuteReader();
referansları değiştirin _Reader = ExecuteReaderWithSetting(_Command);
.
Bunu yapmak aynı zamanda ayarın tek bir konumda yapılmasına izin verirken, çoğunlukla Bul ve Değiştir ile yapılabilecek yalnızca minimal ve basit kod değişikliklerini gerektirir.
Daha da iyisi ( Başka Bölüm 2), bu bir bağlantı seviyesi ayarı olduğundan, her SqlCommand.Execute __ () çağrısı başına yürütülmesi gerekmez. Dolayısıyla ExecuteReader()
, için bir sarmalayıcı oluşturmak yerine , için bir sarmalayıcı oluşturun 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;
}
Ve sonra sadece var olan _Connection.Open();
referansları değiştirin OpenAndSetArithAbort(_Connection);
.
Yukarıdaki fikirlerin her ikisi de, SqlCommand veya SqlConnection'ı genişleten bir Sınıf oluşturarak daha fazla OO tarzında uygulanabilir.
Veya Daha iyisi ( Else Bölüm 3), sen Connection StateChange için bir olay işleyicisi oluşturmak ve özelliğini ayarlayın sahip olabilecekken gelen bağlantı değişiklikleri Closed
için Open
aşağıdaki gibi:
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();
}
}
}
Bu yerinde, yalnızca bir SqlConnection
örnek oluşturduğunuz her yere aşağıdakileri eklemeniz gerekir :
_Connection.StateChange += new StateChangeEventHandler(OnStateChange);
Mevcut kodda değişiklik yapılması gerekmez. Küçük bir konsol uygulamasında bu yöntemi denedim, sonucunu yazdırarak test ettim SELECT SESSIONPROPERTY('ARITHABORT');
. Dönüyor 1
, ancak Olay İşleyiciyi devre dışı bırakırsam döndürür 0
.
Tamlık uğruna, işte işe yaramayan bazı şeyler var (ya hiç ya da etkili biçimde değil):
- Oturum Açma Tetikleyicileri : Aynı oturumda çalışırken ve açıkça başlatılmış bir işlem içinde çalıştırılsa bile, tetikleyiciler hala bir alt işlemdir ve bu nedenle ayarları (
SET
komutlar, yerel geçici tablolar, vb.) Yereldir ve hayatta kalmazlar. bu alt sürecin sonu.
SET ARITHABORT ON;
Her saklı yordamın başlangıcına ekleme :
- Bu, mevcut projeler için, özellikle saklı işlemlerin sayısı arttıkça, çok fazla çalışma gerektirir.
- bu geçici sorgulara yardımcı olmaz