나는 며칠 동안 다음과 같은 일을하고있다.EntityFramework DbContext 수명주기 및 포스트그레스 : "작업이 이미 진행 중입니다."
난 저장소 패턴과 UnitOfWork 및 Postgres를 사용하여 EntityFramework와 함께 Mono에서 실행중인 Nancy 앱을 보유하고 있습니다. Nancy는 TinyIoC를 IoC 컨테이너로 사용합니다.
프런트 엔드에서 요청을 대기열에 두어 나중에 백엔드가 한 번에 한 요청을 받게되는 웹 앱이 있습니다. 이 모든 것이 잘 작동합니다.
그러나 동일한 백엔드에 연결하고 백엔드에 요청을 대기열에 넣지 않고 때때로 거의 동시에 요청을 실행하는 iOS 앱을 실행하면 문제가 발생합니다. 낸시 부트 스트 래퍼에,
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
내가 좋아 종속성을 등록하고 : 임의의 간격으로
는 백엔드이 오류를 던지기 시작
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...
}
나는 이것이 다입니다 느낌이 두 개의 분리 된 요청이 동일한 DbContext (또는 기본 연결)를 사용하여 상황을 폭파하게 만듭니다.
낸시 부트 스트 래퍼의 ConfigureRequestContainer
메소드에 종속성을 등록하려고 시도했지만 '연결이 열려 있지 않습니다.'예외가 발생합니다.
이 문제 뒤에 이론은이 문서에서 명확하게 설명되어 있습니다 : http://mehdi.me/ambient-dbcontext-in-ef6/
다음은 나에게 명확하지 않다 :
- 이 멀티 스레딩 문제가 가정에서 내가 수정 있습니까?
- 각각의 요청이 자신의 DbContext/connection을 사용하도록 확실히해야합니다. 따라서 물건이 충돌하지 않으며, TinyIoC/Nancy를 사용하여 DbContext의 수명주기를 관리해야합니다.
나는 이것이 복잡한 문제임을 이해합니다. 추가 정보가 필요한 경우 알려 주시기 바랍니다.
감사합니다.
그렇습니다. 대부분 단일 DbContext가 여러 스레드에서 사용됩니다. 요청에 따라 새 인스턴스로 컨테이너에 DbContext를 등록하십시오. 그러면 인스턴스를 확인할 때마다 새 인스턴스가 만들어집니다. – Evk
DbContext를 다음과 같이 등록합니다 :'container.Register();'TinyIoC 문서를 올바르게 이해하면 DbContext와 다중 인스턴스를 등록하고 해결할 때마다 새로운 인스턴스를 생성해야합니다. 이것은 내가 지금 그것을 어떻게 설정했는지와 위의 상황을 일으키는 원인이 무엇인지에 대한 것입니다. 즉, 다중 인스턴스 임에도 불구하고 모든 요청에 대해 새로운 인스턴스가 보장되지는 않습니다. –
Corstiaan
아니요 기본적으로 인터페이스를 싱글 톤으로 등록하므로 매번 동일한 인스턴스가 반환되므로 문제가 발생합니다. 컨테이너를 수행하십시오.()을 등록하십시오. AsMultiInstance()를 사용하여 다중 인스턴스로 등록하십시오. –
Evk