none
EF 诡异的事务问题 RRS feed

  • 问题

  • 用过EF code-fist  有一段时间了.对数据库的更新操作通过 

    1.DbContext 的SaveChanges

    2.Database.ExecuteSqlCommand

    有时候要 把这两个操作绑定成一个事务,用以下的方式

    TransactionOptions option = new TransactionOptions();
                        option.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted;
                        using (TransactionScope ts = new TransactionScope(TransactionScopeOption.RequiresNew, option))
                        {
                            // Database.Connection.Open();
                            int result = 0;

                            foreach (var sql in SqlTransList)
                            {
                                result = result + ExecuteSqlCommand(sql.sql, sql.param);
                            }
                  
                            result = result + SaveChanges();
                            ts.Complete();
                            return result;
                        }

    SqlTransList 是已经注册的一个操作的集合。

    按道理说,如果操作都是在同一个数据库,没有跨数据库的表的操作。启动的都应该是 轻量型 事务。不会升级到 分布式事务msdtc.

    这种方式,我运用了几次都没有问题,本身的机子也没有装  MSDTC,数据库也是另外一个服务器,也没有装  msdtc

    直到有一次,连接某个服务器的某个数据库:

    服务器 'HN' 上的 MSDTC 不可用。

    说明: 执行当前 Web 请求期间,出现未经处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。 

    异常详细信息: System.Data.SqlClient.SqlException: 服务器 'HN' 上的 MSDTC 不可用。

    源错误: 
    行 142:                            result = result + context.Submit();
    行 143:                        }
    行 144:                        result = result + SaveChanges();
    行 145:                        ts.Complete();
    行 146:                        return result;



    堆栈跟踪: 
    [SqlException (0x80131904): 服务器 'HM' 上的 MSDTC 不可用。]
       System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) +1754306
       System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) +5295182
       System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) +242
       System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) +1683
       System.Data.SqlClient.SqlDataReader.TryConsumeMetaData() +61
       System.Data.SqlClient.SqlDataReader.get_MetaData() +90
       System.Data.SqlClient.TdsParser.TdsExecuteTransactionManagerRequest(Byte[] buffer, TransactionManagerRequestType request, String transactionName, TransactionManagerIsolationLevel isoLevel, Int32 timeout, SqlInternalTransaction transaction, TdsParserStateObject stateObj, Boolean isDelegateControlRequest) +796
       System.Data.SqlClient.TdsParser.GetDTCAddress(Int32 timeout, TdsParserStateObject stateObj) +45
       System.Data.SqlClient.SqlInternalConnectionTds.GetDTCAddress() +34
       System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction tx) +422
       System.Data.SqlClient.SqlInternalConnection.Enlist(Transaction tx) +5294707
       System.Data.SqlClient.SqlInternalConnectionTds.Activate(Transaction transaction) +5294693
       System.Data.ProviderBase.DbConnectionInternal.ActivateConnection(Transaction transaction) +36
       System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection) +1463
       System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection) +78
       System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection) +167
       System.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConn

    这个错误还是出现了。纳闷了,同样的程序,同样的数据库结构。为什么有的会升级到 分布式事务, 有些不会。

    用的EF是 EntityFramework 4.4.0.0

    请问    启用msdtc 是否跟 服务器或者数据库的 配置有关系,希望高手能解决 ?

     
    • 已移动 ThankfulHeart 2012年8月11日 3:33 数据库EF问题 (发件人:.NET Framework 一般性问题讨论区)
    2012年8月11日 3:26

答案

全部回复

  • DBContext接受一个connection参数的


    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful, so they will appear differently to other users who are visiting your thread for the same problem.
    Visual C++ MVP

    2012年8月11日 4:16
    版主
  • 这里面的操作的确是在  同一个 DBContext 里面的. 为什么会启动分布式事务呢 ?
    2012年8月11日 4:59
  • DBContext接受一个connection参数的


    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful, so they will appear differently to other users who are visiting your thread for the same problem.
    Visual C++ MVP

    这里面的操作的确是在  同一个 DBContext 里面的. 为什么会启动分布式事务呢 ?
    2012年8月11日 5:02
  • 找到原因了  是因为这次连的 是  sql server 2005 

    Update: Please note that the behaviour described in this article only occurs when using SQL Server 2005. SQL Server 2008 (and .NET 3.5+) can handle multiple connections within a transaction without requiring MSDTC promotion.

    参考这篇文章    

    http://www.digitallycreated.net/Blog/48/entity-framework-transactionscope-and-msdtc

    • 已标记为答案 ilikepanda 2012年8月11日 5:26
    2012年8月11日 5:26