不允许新事务,因为会话中正在运行其他线程

时间:2011-06-04 14:25:23

标签: ado.net entity-framework-4

获取“不允许新事务,因为会话中还有其他线程运行”。

它与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"];
        }
    }

4 个答案:

答案 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();
    }
}

并且它有效,它很慢但它有效..

点击此处: SqlException from Entity Framework - New transaction is not allowed because there are other threads running in the session

答案 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();
            }
        }