一見好ましいアプローチ
私は、特にいくつかのコメントに基づいて、次のものが他の人によってすでにテストされているという印象を受けました。しかし、私のテストでは、これらの2つの方法は、.NETを介して接続している場合でも、DBレベルで実際に機能することが示されていますSqlClient
。これらは、他者によってテストおよび検証されています。
サーバー全体
あなたは、設定できるユーザー・オプション・それが現在ビット単位であるものは何でもする、サーバーの構成設定をOR
64とED(の値ARITHABORT
)。ビット単位のOR(|
)を使用せず、代わりに直接割り当て(=
)を実行する場合、既に有効になっている他の既存のオプションはすべて消去されます。
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
データベースレベル
これはALTER DATABASE SETを使用してデータベースごとに設定できます。
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;
手動で。考慮すべきいくつかの方法を次に示します。
IFあなたはEntity Frameworkの6(以降)を使用している、あなたはどちらか試すことができます。
Database.ExecuteSqlCommandを使用します。context.Database.ExecuteSqlCommand("SET ARITHABORT ON;");
これは、各クエリごとではなく、DB接続を開いた後に1回実行されるのが理想的です。
次のいずれかの方法でインターセプターを作成します。
これにより、実行前にSQLを変更できるようになります。この場合、次のようにプレフィックスを付けるだけで済みますSET ARITHABORT ON;
。ここでの欠点は、実行されたかどうかの状態をキャプチャするローカル変数を保存し、そのたびにテストする場合を除き、クエリごとに実行されることです(実際にはそれほど余分な作業ではありませんExecuteSqlCommand
が、おそらく簡単です)。
どちらを使用しても、既存のコードを変更せずに1つの場所でこれを処理できます。
ELSEでは、これを行うラッパーメソッドを作成できます。
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);
です。
上記の両方のアイデアは、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;
各ストアドプロシージャの先頭に追加:
- 特に、ストアドプロシージャの数が増えると、既存のプロジェクトに多くの作業が必要になります
- これはアドホッククエリには役立ちません