【发布时间】:2012-03-13 13:26:48
【问题描述】:
我试图避免在我的应用程序中升级 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 方法的内容进行了锁定,因此一次只能运行一个,那么一切正常,但会出现明显的性能损失。但是,当我删除它时,它会升级。
使用包装器的代码正在使用 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 和引入锁的情况下正常运行?
谢谢
【问题讨论】:
-
您使用的是什么版本的 SQL Server?
-
SQL Express 2008 R2,稍后将进入完整版
-
我有点困惑,添加锁可以防止升级,因为
TransactionScopes 是线程绑定的,锁只影响线程的相互作用,而不影响线程内的操作顺序,除非您的线程引入了非确定性行为,否则我可以看到锁如何改变事物。如果您仍然对答案感兴趣,请让我们更多地了解线程方面的情况。
标签: .net sql-server transactionscope msdtc escalation