アプリケーションでMSDTCエスカレーションを回避しようとしています。 SQL Server Express 2008 R2でLINQを使用していますが、後でフルバージョンを使用します。ネストされたTransactionScopeおよび/またはネストされた接続によってMSDTCエスカレーションが発生する
私は、必要に応じて接続を作成し、できるだけ早く廃棄するデータベースラッパークラスを作成しました。接続文字列は、すべての接続で同じままです。私は、PerformConnectionAction方法の内容を中心にその一つだけをロックをかける場合
var db = new SqlServerDatabaseWrapper(connectionString);
db.PerformDataContextAction(
conn => new SomeDataContext(conn),
context => { /* do something */ }
);
次のように使用される
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);
}
}
}
:ここ
は私のクラスの非常にスリムダウンバージョンです一度に実行することができますが、すべてが機能しますが、顕著なパフォーマンス上のペナルティがあります。しかし、私はそれを削除すると、それはエスカレートします。
ラッパーを使用しているコードはTransactionScopeを使用しており、TransactionScopesのネストまたは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のない、そしてロックを導入することなく、うまく実行できるように、私はリファクタリングん/私のコードを書き直すか、あります?
おかげ
使用しているSQL Serverのバージョンは? – Oded
SQL Express 2008 R2は、後でフルバージョン – enashnash
に置くことをお勧めします。ロックを追加すると、「TransactionScope」がスレッドバインドであり、ロックがスレッドの相互作用にのみ影響を及ぼしますが、順序は影響を受けないので、あなたのスレッドが非決定論的な振る舞いを引き起こさない限り、スレッド内での操作については、ロックがどのように変化するかを見ることができます。あなたがまだ答えに関心があるならば、スレッドに沿って何が起こっているのか、私たちにもっと教えてください。 –