获取“不允许新事务,因为会话中还有其他线程运行”。
它与foreach循环或任何人通常与此消息一起出现问题无关。
我在整个请求中使用带有repositoy模式和公共上下文的EF4。有些事情发生了,无法确切地确定是什么,一旦我尝试使用上下文保存变更,我就会收到此消息,并且只有在我回收应用程序池后它才会消失。
我关闭连接了吗?我该怎么说?我是否为每个请求使用了新的上下文?是。
发生了什么事?有解决办法吗?
编辑:(上下文工厂)
private static Dictionary<string, CoinEntities> _instances;
public static CoinEntities DefaultInstance
{
get
{
if (HttpContext.Current == null)
{ //todo: mock instead. testing.
if (!Instances.ContainsKey("_TEST"))
Instances["_TEST"] = new CoinEntities();
return Instances["_TEST"];
}
if (!Instances.ContainsKey("_DEFAULT"))
Instances["_DEFAULT"] = new CoinEntities();
return Instances["_DEFAULT"];
}
}
答案 0 :(得分:16)
我不认为这只是没有处置上下文的问题(上下文不会保持打开的事务 - 你会因为未提交的更改而看到它)。如果您遇到此问题,则很可能不会在每个请求中使用新的上下文实例,或者您对共享上下文实例(=一个连接)进行了多线程/异步处理。此异常表示多个线程(可能是多个已处理的请求)正在尝试在同一连接上使用自己的事务 - 这是不可能的。
转角案例可以手动处理提供给上下文的连接,但我想如果你使用它,你会提到它。
编辑:
您的工厂不提供每个请求上下文 - 它为所有请求提供单个上下文!该静态字典在所有请求之间共享,因此第一个创建实例并将其存储在_DEFAULT
密钥下,所有其他请求将使用它。
答案 1 :(得分:4)
它与新的EF4隐式交易有关。
这意味着当打开AsEnumerable()或ObjectQuery Entity请求时,您处于事务中,一种逃避它的方法是AsArray()查询,然后您不再处于事务中。另一个可能是通过乐观锁定来关闭事务?但我找不到。
这是我的解决方案
RespondableSites = model.HyperTextLinkEntitySets.OfType<Site>()
.Where(x =>
(
x.moz_RESPONSEDATA != null
&& x.RowState.IndexOf("a=") < 0))
).ToArray();
foreach (var siteObj in RespondableSites)
{
using (var context = new brandshieldDBEntities())
{
ParseResponseData(siteObj);
model.SaveChanges();
}
}
并且它有效,它很慢但它有效..
答案 2 :(得分:1)
请求完成后,您不会处置上下文。您可以通过应用using块来处置上下文...
using (var context = new MyContext())
{
// Do Db stuff and SaveChanges, etc.
}
// context gets disposed automatically here
......或明确地:
context.Dispose();
(这是我的理论基于你到目前为止的输入。)
答案 3 :(得分:0)
试试这段代码。它可能有所帮助。在此代码中,我从数据库中获取所有ID,并使用名为ctx
的数据库上下文的新对象对其进行迭代:
var listOfCourseId = db.Courses.Where(c => c.CourseStatus == 1).Select(c => c.CourseId);
using (var ctx = new UniversityDbContext())
{
foreach (var acourseId in listOfCourseId)
{
Course selectedCors = new Course();
selectedCors = ctx.Courses.Where(id => id.CourseId == acourseId).Single(); //hence use ctx.tableName instead of db.tableName
selectedCors.CourseStatus = 0;
ctx.Entry(selectedCors).State = EntityState.Modified;
ctx.SaveChanges();
}
}