gpt4 book ai didi

c# - 多线程 Entity Framework 事务

转载 作者:太空狗 更新时间:2023-10-29 20:37:41 47 4
gpt4 key购买 nike

我有一个运行多个线程的应用程序。线程不共享 ObjectContext(每个线程都有自己的 - 我知道它们不是线程安全的)。

但是,线程都是在共享事务下运行的。原始线程创建一个 TransactionScope,它派生的每个线程使用主线程上事务中的 DependentTransaction 创建一个 TransactionScope。

当多个 ObjectContext 请求同时运行时,我有时(不总是)得到错误:

System.Data.EntityException occurred
Message=An error occurred while closing the provider connection. See the inner exception for details.

InnerException: System.Transactions.TransactionException
Message=The operation is not valid for the state of the transaction.
Source=System.Transactions
StackTrace:
at System.Transactions.TransactionStatePSPEOperation.get_Status(InternalTransaction tx)
at System.Transactions.TransactionInformation.get_Status()
at System.Data.ProviderBase.DbConnectionInternal.CloseConnection(DbConnection owningObject, DbConnectionFactory connectionFactory)
at System.Data.SqlClient.SqlInternalConnection.CloseConnection(DbConnection owningObject, DbConnectionFactory connectionFactory)
at System.Data.SqlClient.SqlConnection.Close()
at System.Data.EntityClient.EntityConnection.StoreCloseHelper()
InnerException:

我只知道它们同时运行,因为当我在 Debug模式下运行我的单元测试并弹出此异常时,如果我查看正在运行的不同线程,我总是看到至少有一个其他线程在一个 ObjectContext 操作。

此外,在做了一些阅读之后,我尝试将 multipleactiveresultsets=False 添加到我的连接字符串中,但没有任何区别。

这是 Entity Framework 中的错误吗?

最佳答案

问题描述如下:

http://www.b10g.dk/2007/09/07/dependenttransaction-and-multithreading/

锁定 SaveChanges 和 Refresh 调用非常容易,但为了确保在查询执行期间发生锁定,我必须制作一个虚拟查询提供程序,在执行查询时锁定。我真的不应该这样做。 Entity Framework 应该足够健壮,可以开箱即用地处理这个问题……特别是考虑到您并不打算处理自己的连接创建。

这是查询提供程序包装器的代码。 IQueryables 本身和基类 QueryProvider 是基于此处的简单可重用实现 http://blogs.msdn.com/b/mattwar/archive/2007/07/30/linq-building-an-iqueryable-provider-part-i.aspx

    /// <summary>
/// A wrapper for queries executed by EF.
/// </summary>
internal class EntityFrameworkQueryProvider : QueryProvider
{
protected override object Execute(Expression expression)
{
try
{
// this is required due to a bug in how EF multi-threads when Transactions are used.
if (Transaction.Current != null) Monitor.Enter(EntityFrameworkExtensions.SyncRoot);

// enumerate is a simple extension method that forces enumeration of the IQueryable, thus making it actually get executed during the lock
return Expression.Lambda(expression).Compile().DynamicInvoke().Enumerate();
}
finally
{
if (Transaction.Current != null) Monitor.Exit(EntityFrameworkRepositoryProvider.SyncRoot);
}
}
}

关于c# - 多线程 Entity Framework 事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5942930/

47 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com