使用Entity Framework == EntityException并发访问数据库

时间:2011-02-28 15:00:43

标签: sql multithreading wcf entity-framework concurrency

我有一个MS SQL 2008数据库,可以通过LINQ进行数据更新/回溯。

对于繁重的应用程序,我的linq在PerCall实例化模式下由WCF服务访问。这个应用程序有几个线程可以调用服务,而且有几个应用程序同时运行。

我经常发生一些EntityException:

  

发现了System.Data.EntityException     Message =在提供程序连接上启动事务时发生错误。有关详细信息,请参阅内部异常     来源= System.Data.Entity的     堆栈跟踪:          在System.Data.EntityClient.EntityConnection.BeginDbTransaction(IsolationLevel isolationLevel)          在System.Data.EntityClient.EntityConnection.BeginTransaction()          在System.Data.Objects.ObjectContext.SaveChanges(SaveOptions选项)          在D:\ Workspace \ XYZWASDF \ DataServer \ DataServer.cs中的Infoteam.GfK.TOMServer.DataServer.DataServer.SaveChanges():第123行     InnerException:System.Data.SqlClient.SqlException          Message = Une nouvelle transaction n'estpasautoriséeparceque d'autres threads sont en cours d'exécutiondansla session。          Source = .Net SqlClient数据提供程序          错误码= -2146232060          类= 16          LineNumber上= 1          数= 3988          过程=“”          服务器= IFT-srv114          状态= 1          堆栈跟踪:               在System.Data.SqlClient.SqlConnection.OnError(SqlException异常,布尔breakConnection)               在System.Data.SqlClient.SqlInternalConnection.OnError(SqlException异常,布尔breakConnection)               在System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()               在System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior,SqlCommand cmdHandler,SqlDataReader dataStream,BulkCopySimpleResultSet bulkCopyHandler,TdsParserStateObject stateObj)               at System.Data.SqlClient.TdsParser.TdsExecuteTransactionManagerRequest(Byte [] buffer,TransactionManagerRequestType request,String transactionName,TransactionManagerIsolationLevel isoLevel,Int32 timeout,SqlInternalTransaction transaction,TdsParserStateObject stateObj,Boolean isDelegateControlRequest)               在System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransactionYukon(TransactionRequest transactionRequest,String transactionName,IsolationLevel iso,SqlInternalTransaction internalTransaction,Boolean isDelegateControlRequest)               at System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransaction(TransactionRequest transactionRequest,String name,IsolationLevel iso,SqlInternalTransaction internalTransaction,Boolean isDelegateControlRequest)               在System.Data.SqlClient.SqlInternalConnection.BeginSqlTransaction(IsolationLevel iso,String transactionName)               在System.Data.SqlClient.SqlInternalConnection.BeginTransaction(IsolationLevel iso)               在System.Data.SqlClient.SqlConnection.BeginDbTransaction(IsolationLevel isolationLevel)               在System.Data.Common.DbConnection.BeginTransaction(IsolationLevel isolationLevel)               在System.Data.EntityClient.EntityConnection.BeginDbTransaction(IsolationLevel isolationLevel)          InnerException:

(抱歉,它不太可读)。 (内部异常的消息表示“不允许新事务,因为会话中正在运行其他线程。”

我已经检查过,我不是在循环中,当它出现这种异常时它是纯粹随机的,我不知道如何避免这种情况。

任何帮助都将非常感激:)

谢谢!

编辑:这是我得到此异常的例子有时候

    //My DataServer method, which is a singleton

    [MethodImpl(MethodImplOptions.Synchronized)]
            public void SaveChanges()
            {
                lock (_lockObject)
                {
                    try
                    {
                        _context.SaveChanges(SaveOptions.AcceptAllChangesAfterSave);
                        _changeListener.ManageIDAfterInsert();                       
                    }
                    catch (Exception ex)
                    {
                        Logger.Instance.Error("[DataServer:SaveChanges] Got an error when trying to save an object", ex);
                        //HERE I've this error
                    }
                }
            }

//One example where I can have exception sometimes, this is called through a WCF service, so I have a method which attach the object and then save it
private OrderStatus AddOrderStatus(OrderStatus orderStatus)
        {
            DataServer.DataServer.Instance.InsertOrUpdateDetachedObject(orderStatus);

            return orderStatus;
        }

1 个答案:

答案 0 :(得分:7)

没有看到你的代码,简短的回答是EntityFramework不是线程安全的。当尝试访问ObjectContext时,当两个+线程重叠时,您会以看似随机的模式收到此错误。我假设您已将上下文填充到static变量中。要么使上下文成为局部变量,要么围绕对ObjectContext的访问进行写锁定。

如果您想要更具体的答案,您的代码将有所帮助。

修改

你的问题是两个线程正在尝试同时使用上下文,或者一个线程正在打开一个事务,然后第二个线程试图使用你的单例上下文。您的代码片段为我提出了比以前更多的问题。

  • 在您的代码示例中,_ lockObject是一个静态变量?
  • 为什么要在SaveChanges中显示锁定,然后解释正在抛出的错误 来自InsertOrUpdateDetachedObject?我们能看到InsertOrUpdateDetachedObject的代码吗?
  • SaveChanges是否使用与直接访问上下文的所有其他方法相同的_lockObject
  • 您对_context.SaveChanges的呼叫是您保存到数据库的唯一方式,还是您有自己打开事务上下文的其他区域?
  • 您使用单身人士,以便在多个来电之间共享您的上下文。可能最好为每个WFC调用实例化一个新的新上下文。