我有一个 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/