Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 导致MSDTC升级的嵌套TransactionScope和/或嵌套连接_.net_Sql Server_Transactionscope_Msdtc_Escalation - Fatal编程技术网

.net 导致MSDTC升级的嵌套TransactionScope和/或嵌套连接

.net 导致MSDTC升级的嵌套TransactionScope和/或嵌套连接,.net,sql-server,transactionscope,msdtc,escalation,.net,Sql Server,Transactionscope,Msdtc,Escalation,我试图在我的应用程序中避免MSDTC升级。我正在将LINQ与SQL Server Express 2008 R2一起使用,稍后将使用完整版本 我已经编写了一个数据库包装器类,它可以根据需要创建连接并尽快处理它们。连接字符串在所有连接中保持不变 以下是我的班级精简版: public class SqlServerDatabaseWrapper { public SqlServerDatabaseWrapper(string connectionString) { Connection

我试图在我的应用程序中避免MSDTC升级。我正在将LINQ与SQL Server Express 2008 R2一起使用,稍后将使用完整版本

我已经编写了一个数据库包装器类,它可以根据需要创建连接并尽快处理它们。连接字符串在所有连接中保持不变

以下是我的班级精简版:

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);
    }
  }
}
如果我对PerformConnectionAction方法的内容设置了一个锁,这样一次只能运行一个,那么一切都正常,但会有明显的性能损失。但是,当我删除它时,它会升级

使用包装器的代码正在使用TransactionScope,并且可能存在TransactionScope嵌套和/或对PerformDataContextAction或PerformConnectionAction的调用(每个调用都使用相同的连接字符串创建新连接);在伪代码中(因为这可能发生在不同的类/方法中):

还要注意的是,静态成员方法的使用可能发生在不同的点上

我还要补充一点,连接字符串如下所示:

var db = new SqlServerDatabaseWrapper(connectionString);
db.PerformDataContextAction(
  conn => new SomeDataContext(conn), 
  context => { /* do something */ }
);
Data Source=.\SQLEXPRESS;Initial Catalog=db1;User Id=test1;Password=test1;MultipleActiveResultSets=true;Enlist=false;
问题是,我如何重构/重写代码,使我的应用程序能够在没有MSDTC和引入锁的情况下运行良好


谢谢

您是否只使用一个到事务范围内数据库的连接? 在事务作用域内创建两个具有相同或不同连接字符串的连接将使事务升级为分布式事务

您可以将连接存储在线程静态变量中,并在事务中的所有工作完成后关闭/处置它。然后每个线程都有自己的连接


当您向逻辑添加锁时,您可能无法获得分布式事务,因为连接池每次都会返回相同的连接。

您使用的是哪个版本的SQL Server?SQL Express 2008 R2,稍后将进入完整版本我有点困惑,添加锁可以防止升级,因为
TransactionScope
s是线程绑定的,锁只影响线程之间的相互作用,而不影响线程内部的操作顺序,除非线程引入了非确定性行为,我可以看到锁是如何改变事情的。如果您仍然对答案感兴趣,请让我们了解更多关于线程方面的内容。
Data Source=.\SQLEXPRESS;Initial Catalog=db1;User Id=test1;Password=test1;MultipleActiveResultSets=true;Enlist=false;