我试图在DB上保存一个多线程进程的日志,但我得到以下错误:不允许新事务,因为有其他线程在会话中运行。
在中,我有这个函数:
internal bool WriteTrace(IResult result, string message, byte type)
{
SPC_SENDING_TRACE trace = new SPC_SENDING_TRACE(
message,
Parent.currentLine.CD_LINE,
type,
Parent.currentUser.FULLNAME,
Parent.guid);
Context.SPC_SENDING_TRACE.AddObject(trace);
if (Context.SaveChanges(result) == false)
return false;
return true;
}
每个线程的上下文是不同的,但是与DB的连接总是相同的。
有办法解决这个问题吗?
谢谢安德里亚
您应该为每个事务创建一个上下文,然后处理它,您可以这样做:
using(var ctx = new MyContext()) {
//do transaction here
}
在右括号之后,上下文被丢弃。
为了更好地理解,参考这篇文章,你可以找到ken2k的一个很好的答案。希望你能解决你的问题:)
更新:
您还应该尝试将.ToList()
添加到您拥有的每个LINQ查询中。当迭代LINQ结果时,在迭代完成之前不能进行任何更改。检查一下你是否有类似的东西,或者分享更多的代码,比如你调用WriteTrace
的代码。希望这次能帮到你
我在多线程环境中使用实体框架,其中任何线程,ui和后台(STA和MTA)都可以并发地更新同一个数据库。我通过在任何新的后台线程开始使用时从头开始重新创建实体连接来解决这个问题。检查实体连接实例ConnectionString显示了一个阅读器指南,我假设它用于链接普通连接实例。通过从头开始重新创建实体连接,每个线程的guid值是不同的,并且不会发生冲突。
// Build the connection string.
var sqlBuilder = new SqlConnectionStringBuilder();
sqlBuilder.DataSource = serverName;
sqlBuilder.InitialCatalog = databaseName;
sqlBuilder.MultipleActiveResultSets = true;
...
var providerString = sqlBuilder.ToString();
var sqlConnection = new SqlConnection(providerString);
// Build the emtity connection.
Assembly metadataAssembly = Assembly.GetExecutingAssembly();
Assembly[] metadataAssemblies = { metadataAssembly };
var metadataBase = @"res://*/{0}.csdl|res://*/{0}.ssdl|res://*/{0}.msl";
var dbModelMetadata = String.Format(metadataBase, objectContextTypeModelName);
// eg: "res://*/Models.MyDatabaseModel.csdl|res://*/Models.MyDatabaseModel.ssdl|res://*/Models.MyDatabaseModel.msl"
var modelMetadataPaths = modelMetadata.Split('|');
var metadataWorkspace = new MetadataWorkspace(modelMetadataPaths, metadataAssemblies);
var entityDbConnection = new EntityConnection(metadataWorkspace, sqlConnection);
return entityDbConnection;