アプリケーションで MSDTC エスカレーションを回避しようとしています。SQL Server Express 2008 R2 で LINQ を使用していますが、後でフル バージョンを使用する予定です。
必要に応じて接続を作成し、できるだけ迅速に破棄するデータベース ラッパー クラスを作成しました。接続文字列は、すべての接続で同じままです。
これは私のクラスの非常にスリム化されたバージョンです:
public class SqlServerDatabaseWrapper {
public SqlServerDatabaseWrapper(string connectionString) {
ConnectionString = connectionString;
}
public string ConnectionString { get; private set; }
private static IDbConnection GetOpenConnection() {
var conn = new SqlConnection(ConnectionString);
conn.Open();
return conn;
}
// there is also a second method to return a value
// there is PerformCommandAction for SqlCommand as well
public void PerformDataContextAction<TContext>(Func<IDbConnection, TContext> creator, Action<TContext> action) where TContext : DataContext {
PerformConnectionAction(conn => {
using (var context = creator(conn))
action(context);
});
}
// there is also a second method to return a value
public void PerformConnectionAction(Action<IDbConnection> action) {
using (IDbConnection conn = GetOpenConnection(ConnectionString)) {
action(conn);
}
}
}
次のように使用します。
var db = new SqlServerDatabaseWrapper(connectionString);
db.PerformDataContextAction(
conn => new SomeDataContext(conn),
context => { /* do something */ }
);
PerformConnectionAction メソッドの内容をロックして、一度に 1 つしか実行できないようにすると、すべてが機能しますが、パフォーマンスが著しく低下します。ただし、削除するとエスカレートします。
ラッパーを使用しているコードは TransactionScope を使用しており、TransactionScope のネストおよび/または PerformDataContextAction または PerformConnectionAction の呼び出し (それぞれが同じ接続文字列で新しい接続を作成する) が存在する可能性があります。疑似コードで (これは異なるクラス/メソッドで発生する可能性があるため):
var db = new SqlServerDatabaseWrapper(connectionString)
using (TransactionScope tran = new TransactionScope()) {
db.PerformDataContextAction(
/* ... */,
context => {
using (TransactionScope tran2 = new TransactionScope()) {
db.PerformConnectionAction(conn => { /* some stuff */ });
tran2.Complete();
}
}
tran.Complete();
}
また、さまざまな時点で発生する可能性のある静的メンバーシップ メソッドが使用されていることにも注意してください。
また、接続文字列が次のようになっていることも付け加えておきます。
Data Source=.\SQLEXPRESS;Initial Catalog=db1;User Id=test1;Password=test1;MultipleActiveResultSets=true;Enlist=false;
問題は、MSDTC を使用せず、ロックを導入せずに、アプリケーションが適切に動作するようにコードをリファクタリング/リライトするにはどうすればよいかということです。
ありがとう