【问题标题】:Concurrent access to a database with Entity Framework == EntityException使用 Entity Framework == EntityException 并发访问数据库
【发布时间】:2011-07-05 20:14:04
【问题描述】:

我有一个 MS SQL 2008 数据库,可通过 LINQ 访问以进行数据更新/检索。

WCF 服务以 PerCall 实例化模式访问我的 linq,以用于繁重的应用程序。该应用程序有多个线程调用服务,并且多个应用程序同时运行。

我经常发生一些 EntityException:

System.Data.EntityException 被捕获 Message=在提供程序连接上启动事务时发生错误。有关详细信息,请参阅内部异常。 源=系统.数据.实体 堆栈跟踪: 在 System.Data.EntityClient.EntityConnection.BeginDbTransaction(IsolationLevel 隔离级别) 在 System.Data.EntityClient.EntityConnection.BeginTransaction() 在 System.Data.Objects.ObjectContext.SaveChanges(SaveOptions 选项) 在 D:\Workspace\XYZWASDF\DataServer\DataServer.cs:line 123 中的 Infoteam.GfK.TOMServer.DataServer.DataServer.SaveChanges() 内部异常:System.Data.SqlClient.SqlException Message=Une nouvelle transaction n'est pas autorisée parce que d'autres threads Sont en cours d'execution dans la session。 Source=.Net SqlClient 数据提供者 错误代码=-2146232060 班级=16 行号=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) 在 System.Data.SqlClient.TdsParser.TdsExecuteTransactionManagerRequest(字节 [] 缓冲区,TransactionManagerRequestType 请求,字符串 transactionName,TransactionManagerIsolationLevel isoLevel,Int32 超时,SqlInternalTransaction 事务,TdsParserStateObject stateObj,布尔 isDelegateControlRequest) 在 System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransactionYukon(TransactionRequest transactionRequest,字符串 transactionName,IsolationLevel iso,SqlInternalTransaction internalTransaction,布尔 isDelegateControlRequest) 在 System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransaction(TransactionRequest transactionRequest,字符串名称,IsolationLevel iso,SqlInternalTransaction internalTransaction,布尔 isDelegateControlRequest) 在 System.Data.SqlClient.SqlInternalConnection.BeginSqlTransaction(IsolationLevel iso,字符串 transactionName) 在 System.Data.SqlClient.SqlInternalConnection.BeginTransaction(IsolationLevel iso) 在 System.Data.SqlClient.SqlConnection.BeginDbTransaction(IsolationLevel 隔离级别) 在 System.Data.Common.DbConnection.BeginTransaction(IsolationLevel 隔离级别) 在 System.Data.EntityClient.EntityConnection.BeginDbTransaction(IsolationLevel 隔离级别) 内部异常:

(对不起,它不是很可读)。 (内部异常消息的意思是“A new transaction is not allowed because there are other threads running in the session.”

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

任何帮助将不胜感激:)

谢谢!

编辑:这是我有时遇到此异常的示例

    //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;
        }

【问题讨论】:

  • 你能显示导致这个错误的代码吗?

标签: sql multithreading wcf entity-framework concurrency


【解决方案1】:

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

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

编辑

您的问题是两个线程同时尝试使用上下文,或者 1 个线程使事务处于打开状态,而第二个线程试图使用您的单例上下文。您的代码 sn-p 对我提出了比以前更多的问题。

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

【讨论】:

  • 我添加了一个示例,有时我会遇到一些崩溃。创建数据服务器的我的 DataServer 是一个单例,但我想这是因为我有一个 PerCall 实例化,不同的调用具有不同的上下文
  • 您好,我没有从上面得到答案。你能帮我清理一下吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-06
  • 2020-05-02
  • 2019-02-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多