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

J4N*_*J4N 8 sql concurrency wcf multithreading entity-framework

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

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

我经常发生一些EntityException:

捕获到System.Data.EntityException消息=在提供程序连接上启动事务时发生错误.有关详细信息,请参阅内部异常 Source = System.Data.Entity StackTrace:位于System.Data.EntityClient.EntityConnection.BeginTransaction()处的System.Data.EntityClient.EntityConnection.BeginDbTransaction(IsolationLevel isolationLevel),位于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 encoursd'exécutiondansla session.Source = .Net SqlClient Data Provider ErrorCode = -2146232060 Class = 16 LineNumber = 1 Number = 3988 Procedure =""Server = ift-srv114 State = 1 StackTrace:at System.Data.SqlClient.SqlConnection.OnError(SqlException exception,Boolean breakConnection )在System.Data.SqlClient.TdsParser.Run的System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()处的System.Data.SqlClient.SqlInternalConnection.OnError(SqlException异常,布尔breakConnection)(RunBehavior runBehavior,SqlCommand cmdHandler,SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler,TdsParserStateObject stateObj)在System.Data.SqlClient上的System.Data.SqlClient.TdsParser.TdsExecuteTransactionManagerRequest(Byte []缓冲区,TransactionManagerRequestType请求,String transactionName,TransactionManagerIsolationLevel isoLevel,Int32超时,SqlInternalTransaction事务,TdsParserStateObject stateObj,Boolean isDelegateControlRequest). SqlInternalConnectionTds.ExecuteTransactionYukon(TransactionRequest transacti 在System.Data.SqlClient.SqlInternalConnection.BeginSqlTransaction的System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransaction(TransactionRequest transactionRequest,String name,IsolationLevel iso,SqlInternalTransaction internalTransaction,Boolean isDelegateControlRequest)中的onRequest,String transactionName,IsolationLevel iso,SqlInternalTransaction internalTransaction,Boolean isDelegateControlRequest) (System.Data.SqlClient.SqlInternalConnection.BeginTransaction(IsolationLevel iso)中的System.Data.SqlClient.SqlConnection.BeginDbTransaction(IsolationLevel isolationLevel)处于System.Data.Common.DbConnection.BeginTransaction(IsolationLevel isolationLevel)处的(IsolationLevel iso,String transactionName)at at 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;
        }
Run Code Online (Sandbox Code Playgroud)

EBa*_*arr 7

没有看到你的代码,简短的回答是EntityFramework不是线程安全的.当尝试访问您的两个+线程重叠时,您会以看似随机的模式获得此错误ObjectContext.我假设你已经将你的上下文填充到一个static变量中了.要么将上下文设置为局部变量,要么围绕访问权限写入锁定ObjectContext.

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

编辑

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

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