Новая транзакция не разрешена, потому что в сеансе запущены другие потоки - PullRequest
8 голосов
/ 04 июня 2011

Получение "новой транзакции не разрешено, поскольку в сеансе запущены другие потоки".

Это не имеет ничего общего с циклами foreach или с чем-то, с чем люди обычно сталкиваются в связи с этим сообщением.

Я использовал 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 ]

16 голосов
/ 04 июня 2011

Я не думаю, что это только проблема неразмещенных контекстов (контекст не сохраняет открытую транзакцию - вы увидите ее из-за незафиксированных изменений).Если у вас есть эта проблема, вы, скорее всего, не используете новый экземпляр контекста для запроса или у вас есть некоторая многопоточная / асинхронная обработка на экземпляре общего контекста (= одно соединение).Это исключение говорит о том, что несколько потоков (возможно, несколько обработанных запросов) пытаются использовать свои собственные транзакции для одного и того же соединения - это невозможно.

Угловой регистр может быть ручной обработкой соединений, предоставляемых контексту, но я полагаю, вы упомянули бы об этом, если бы использовали его.контекст запроса - он обеспечивает единый контекст для всего запроса !!!Этот статический словарь является общим для всех запросов, поэтому первый создает экземпляр и сохраняет его под ключом _DEFAULT, и все остальные запросы будут использовать его.

4 голосов
/ 21 мая 2012

Это связано с новой неявной транзакцией 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 из Entity Framework - Новая транзакция не разрешена, поскольку в сеансе запущены другие потоки

1 голос
/ 04 июня 2011

Вы не располагаете контекстом, когда ваш запрос завершен. Вы можете избавиться от контекста, применив блок using ...

using (var context = new MyContext())
{
    // Do Db stuff and SaveChanges, etc.
}
// context gets disposed automatically here

... или явно:

context.Dispose();

(Это моя теория, основанная на ваших данных.)

0 голосов
/ 24 августа 2014

Попробуйте этот код.Это может помочь.В этом коде я беру все идентификаторы из базы данных и перебираю их с новым объектом контекста базы данных с именем 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();
            }
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...