Entity Framework + Autofac — случайные ошибки при сохранении

Использование autofac в качестве инфраструктуры IoC.
Я хочу иметь возможность настроить экземпляр DbContext при запуске приложения.

В моем проекте ASP.NET MVC 3 я регистрирую экземпляр DbContext в Global.asax (PerLifetimeScope). Но когда я запускаю свой сайт в нескольких браузерах (или нескольких вкладках) одновременно, иногда я получаю Object reference not set to an instance of an object. или New transaction is not allowed because there are other threads running in the session при попытке сохранить изменения обратно в базу данных. Также я иногда получаю ExecuteReader requires an open and available Connection. The connection's current state: Broken., когда хочу прочитать данные из базы данных.

ошибки появляются случайно, и я подозреваю, что это как-то связано с жизненным циклом моего контекста. вот переопределенный метод SaveChange моего DbContext.

public class MyContext : DbContext
{ 
    public override int SaveChanges()
    {
        var result = base.SaveChanges(); // Exception here
    }
}

Вот как я регистрирую свой контекст:

builder.Register(c => new MyContext("SomeConnectionString"))
                 .InstancePerLifetimeScope(); 

Если у меня есть только одна открытая вкладка моего сайта в браузере, все работает нормально.
Также стоит упомянуть, что у меня есть CRUD-операции с базой данных каждые 5-10 секунд на моем веб-сайте, вызывая метод контроллера с использованием Ajax.

StackTrace для New transaction is not allowed because there are other threads running in the session:

at System.Data.EntityClient.EntityConnection.BeginDbTransaction(IsolationLevel isolationLevel)
at System.Data.EntityClient.EntityConnection.BeginTransaction()
at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options)
at System.Data.Entity.Internal.InternalContext.SaveChanges()
at System.Data.Entity.Internal.LazyInternalContext.SaveChanges()
at System.Data.Entity.DbContext.SaveChanges()
at MyProject.Data.MyContext.SaveChanges() in D:\Test.cs

StackTrace для Object reference not set to an instance of an object.:

at System.Data.Objects.ObjectStateManager.DetectConflicts(IList`1 entries)
at System.Data.Objects.ObjectStateManager.DetectChanges()
at System.Data.Entity.Internal.InternalContext.DetectChanges(Boolean force)
at System.Data.Entity.Internal.InternalContext.GetStateEntries(Func`2 predicate)
at System.Data.Entity.Internal.InternalContext.GetStateEntries()
at System.Data.Entity.Infrastructure.DbChangeTracker.Entries()
at System.Data.Entity.DbContext.GetValidationErrors()
at System.Data.Entity.Internal.InternalContext.SaveChanges()
at System.Data.Entity.Internal.LazyInternalContext.SaveChanges()
at System.Data.Entity.DbContext.SaveChanges()
at MyProject.Data.MyContext.SaveChanges() in D:\Test.cs   at 

person Kamyar    schedule 16.07.2012    source источник
comment
это помогает? stackoverflow.com/questions/6237280/ запущены другие потоки.   -  person Boomer    schedule 16.07.2012
comment
Насколько я понимаю, InstancePerLifetimeScope должен обрабатывать создание/удаление контекста для каждого HttpRequest отдельно. Если нет, то есть ли у вас какие-либо рекомендации по написанию пользовательского менеджера области действия для моего контекста?   -  person Kamyar    schedule 16.07.2012
comment
Я тоже заметил эту проблему   -  person sky-dev    schedule 30.07.2012


Ответы (2)


Регистрация MyContext выглядит нормально. Возможно ли, что какая-то другая служба, которая принимает MyContext, зарегистрирована как синглтон и используется несколькими потоками?

person Jim Bolla    schedule 16.07.2012
comment
Никогда не думал об этом. Вы были правы насчет синглтона, имеющего доступ к контексту, но даже после его удаления я все еще вижу странные ошибки контекста. Попробую еще накопать. - person Kamyar; 17.07.2012

У меня была та же проблема: спорадические ошибки, связанные с DbContext, при использовании Autofac для разрешения DbContext.

{System.Data.EntityCommandExecutionException: An error occurred while executing the command definition. See the inner exception for details.
etc.

{System.NullReferenceException: Object reference not set to an instance of an object.
at System.Data.Objects.ObjectStateManager.DetectConflicts(IList`1 entries)
etc.

Я нашел класс, похожий на следующий в моем коде. Разрешение зависимостей происходило внутри статического метода внутри синглтона. Разрешаемый объект имел зависимость от DbContext. У меня не было никаких дополнительных проблем после того, как я нашел способ реструктурировать этот класс, чтобы он больше не был синглтоном.

Возможно, у вас похожая ситуация? Еще одна вещь, которую можно попробовать, — это сделать ваш DbContext InstancePerHttpRequest. Это может помочь определить, является ли это проблемой.

public class Singleton
{
    private static Singleton _instance = new Singleton();

    private Singleton()
    {

    }

    public static void DoSomething<TSource>(TSource source) where TSource : ISource
    {
        var items = DependencyResolver.Current.Resolve<IEnumerable<IDbContextConsumer<TSource>>>();
        foreach (var item in items)
        {
            item.Execute(source);
        }
    }
}
person sky-dev    schedule 30.07.2012