Ciclo de vida do EntityFramework DbContext + Postgres: “Uma operação já está em andamento.”

Estou mexendo no seguinte há alguns dias.

Eu tenho um aplicativo Nancy em execução no Mono, com EntityFramework com padrão de repositório e UnitOfWork e Postgres. Nancy usa o TinyIoC como seu contêiner de IoC.

Eu tenho um aplicativo Web que enfileira solicitações no front-end para que o back-end seja atingido, um pedido por vez. Tudo isso funciona bem.

No entanto, o problema começa quando eu executo um aplicativo iOS que se conecta ao mesmo back-end e não enfileira solicitações ao back-end, acionando a solicitação às vezes quase simultaneamente.

Em intervalos aleatórios, o back-end começa a gerar este erro:

2016-09-20T13:30:16.120057436Z app[web.1]: System.Data.Entity.Core.EntityCommandExecutionException: An error occurred while executing the command definition. See the inner exception for details. ---> System.InvalidOperationException: An operation is already in progress.
2016-09-20T13:30:16.120104535Z app[web.1]:   at Npgsql.NpgsqlConnector.StartUserAction (ConnectorState newState) <0x41ad0150 + 0x00313> in <filename unknown>:0
2016-09-20T13:30:16.120113254Z app[web.1]:   at Npgsql.NpgsqlCommand.ExecuteDbDataReaderInternal (CommandBehavior behavior) <0x41acfe30 + 0x0002f> in <filename unknown>:0
2016-09-20T13:30:16.120119308Z app[web.1]:   at Npgsql.NpgsqlCommand.ExecuteDbDataReader (CommandBehavior behavior) <0x41acfe00 + 0x00013> in <filename unknown>:0
2016-09-20T13:30:16.120125313Z app[web.1]:   at System.Data.Common.DbCommand.ExecuteReader (CommandBehavior behavior) <0x41f1a3c0 + 0x00018> in <filename unknown>:0
2016-09-20T13:30:16.120131185Z app[web.1]:   at (wrapper remoting-invoke-with-check) System.Data.Common.DbCommand:ExecuteReader (System.Data.CommandBehavior)
2016-09-20T13:30:16.120206045Z app[web.1]:   at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.<Reader>b__c (System.Data.Common.DbCommand t, System.Data.Entity.Infrastructure.Interception.DbCommandInterceptionContext`1 c) <0x41f1ac20 + 0x00027> in <filename unknown>:0
2016-09-20T13:30:16.120220450Z app[web.1]:   at System.Data.Entity.Infrastructure.Interception.InternalDispatcher`1[TInterceptor].Dispatch[TTarget,TInterceptionContext,TResult] (System.Data.Entity.Infrastructure.Interception.TTarget target, System.Func`3 operation, System.Data.Entity.Infrastructure.Interception.TInterceptionContext interceptionContext, System.Action`3 executing, System.Action`3 executed) <0x41b1d3c0 + 0x0010e> in <filename unknown>:0
2016-09-20T13:30:16.120232740Z app[web.1]:   at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.Reader (System.Data.Common.DbCommand command, System.Data.Entity.Infrastructure.Interception.DbCommandInterceptionContext interceptionContext) <0x41f1a880 + 0x00263> in <filename unknown>:0
2016-09-20T13:30:16.120267802Z app[web.1]:   at System.Data.Entity.Internal.InterceptableDbCommand.ExecuteDbDataReader (CommandBehavior behavior) <0x41f1a3f0 + 0x000e6> in <filename unknown>:0
2016-09-20T13:30:16.120274613Z app[web.1]:   at System.Data.Common.DbCommand.ExecuteReader (CommandBehavior behavior) <0x41f1a3c0 + 0x00018> in <filename unknown>:0
2016-09-20T13:30:16.120318116Z app[web.1]:   at (wrapper remoting-invoke-with-check) System.Data.Common.DbCommand:ExecuteReader (System.Data.CommandBehavior)
2016-09-20T13:30:16.120326788Z app[web.1]:   at System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition.ExecuteStoreCommands (System.Data.Entity.Core.EntityClient.EntityCommand entityCommand, CommandBehavior behavior) <0x41f154c0 + 0x00043> in <filename unknown>:0
2016-09-20T13:30:16.120332587Z app[web.1]:   --- End of inner exception stack trace ---
2016-09-20T13:30:16.120336995Z app[web.1]:   at System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition.ExecuteStoreCommands (System.Data.Entity.Core.EntityClient.EntityCommand entityCommand, CommandBehavior behavior) <0x41f154c0 + 0x000b3> in <filename unknown>:0
2016-09-20T13:30:16.120344218Z app[web.1]:   at System.Data.Entity.Core.Objects.Internal.ObjectQueryExecutionPlan.Execute[TResultType] (System.Data.Entity.Core.Objects.ObjectContext context, System.Data.Entity.Core.Objects.ObjectParameterCollection parameterValues) <0x41f11e50 + 0x000a4> in <filename unknown>:0

Estou registrando as dependências como no bootstrapper de Nancy:

protected override void ConfigureApplicationContainer (TinyIoCContainer container)
        {
            base.ConfigureApplicationContainer (container);

            Database.SetInitializer<ReflectDbContext> (new NullDatabaseInitializer<ReflectDbContext> ()); // add this to allow prevent "The context cannot be used while the model is being created"

        container.Register<IReflectDbContext, ReflectDbContext> ();
        container.Register<ReflectUnitOfWork> ().AsSingleton ();

        container.Register<IReflectUserRepository, ReflectUserRepository> ();
        container.Register<IUserRepository<ReflectUser>, ReflectUserRepository> ();

        container.Register<IReviewRepository, ReviewRepository> ();

        container.Register<IReviewSetupRepository, ReviewSetupRepository> ();

        container.Register<IRepositoryV2<ReflectUserActivityItem>, EntityFrameworkRepository<ReflectUserActivityItem>> ();

        container.Register<IAuthenticationUnitOfWork<ReflectUser, ReflectUserActivityItem>, ReflectUnitOfWork> ();

        container.Register<IRepository<ReflectUserActivityItem>, NullRepository<ReflectUserActivityItem>> (); //TODO remove this when port is complete

        container.Register<IErrorLogger, SimpleLogLogger> ();
        container.Register<IGeoIpDataProvider, TelizeGeoIpDataProvider> ();
        container.Register<IRepository<ReviewSetup>, ServiceStackOrmLiteRepository<ReviewSetup>> ();
        container.Register<IEmailExporter, MailChimpUserEmailDataExporter> ();
        container.Register<IMailer, SmtpMailer> ();
        container.Register<IUserManager<ReflectUser>, UserManager<ReflectUser, ReflectUserActivityItem>> ();
        container.Register<IUserMessageManager<ReflectUser>, UserMessageManager<ReflectUser>> ();

etc...

}

Tenho a sensação de que esse é um problema com vários threads e que duas solicitações separadas estão usando o mesmo DbContext (ou conexão subjacente) que faz com que as coisas explodam.

Eu já tentei registrar as dependências no diretórioConfigureRequestContainer do bootstrapper de Nancy, mas isso gera uma exceção 'Connection is not open`.

A teoria por trás desta questão é explicada claramente neste artigo:http://mehdi.me/ambient-dbcontext-in-ef6/

O seguinte não está claro para mim:

Estou correto ao supor que este é um problema com vários threads?Preciso conhecer a maneira correta de garantir que cada solicitação use seu próprio DbContext / conexão para que as coisas não colidam, usando o TinyIoC / Nancy de forma perferível para gerenciar o ciclo de vida do DbContext.

Entendo que esta é uma questão complexa. Entre em contato se precisar de mais informações.

Obrigado :-).

questionAnswers(1)

yourAnswerToTheQuestion