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

标签 sql multithreading wcf entity-framework concurrency

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

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

我经常发生一些EntityException:

System.Data.EntityException was caught Message=An error occurred while starting a transaction on the provider connection. See the inner exception for details. Source=System.Data.Entity StackTrace: at System.Data.EntityClient.EntityConnection.BeginDbTransaction(IsolationLevel isolationLevel) at System.Data.EntityClient.EntityConnection.BeginTransaction() at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options) at Infoteam.GfK.TOMServer.DataServer.DataServer.SaveChanges() in D:\Workspace\XYZWASDF\DataServer\DataServer.cs:line 123 InnerException: System.Data.SqlClient.SqlException Message=Une nouvelle transaction n'est pas autorisée parce que d'autres threads sont en cours d'exécution dans la 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) at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() at 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) at 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) at System.Data.SqlClient.SqlInternalConnection.BeginSqlTransaction(IsolationLevel iso, String transactionName) at System.Data.SqlClient.SqlInternalConnection.BeginTransaction(IsolationLevel iso) at System.Data.SqlClient.SqlConnection.BeginDbTransaction(IsolationLevel isolationLevel) at System.Data.Common.DbConnection.BeginTransaction(IsolationLevel isolationLevel) at System.Data.EntityClient.EntityConnection.BeginDbTransaction(IsolationLevel isolationLevel) InnerException:

(抱歉,它的可读性不太好)。 (内部异常的消息意思是“不允许新事务,因为 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;
        }

最佳答案

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

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

编辑

您的问题是两个线程尝试同时使用上下文,或者 1 个线程将事务保持打开状态,而第二个线程尝试使用您的单例上下文。你的代码片段给我带来了比以前更多的问题。

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

关于sql - 使用 Entity Framework == EntityException 并发访问数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5143615/

相关文章:

c# - 无效操作异常 : The calling thread cannot access this object because a different thread owns it.

.net - 本地计算机上的服务启动然后停止,如果其他服务或程序未使用某些服务会自动停止

php - 如何查询5分钟内插入2次以上,邮箱地址相同,status=1的重复记录?

sql - where 子句中的多个 'in' 语句需要相互匹配

c# - 将 *.mdf 文件添加到 C# 项目

.net - 在 .NET WCF 服务部署上选择 Azure 或 AWS

WCF 通过 HTTPS -> 代理 -> HTTP

sql - Derby 列名在使用 ij 时被截断

Java 7 : Thread reuse?(断开-重新连接)

c - 全局客户表 C : Chatroom