私は数日間、次のことを今や混乱させてきました。EntityFramework DbContextライフサイクル+ Postgres: "操作は既に進行中です。"
私はMono、EntityFrameworkとRepositoryパターン、UnitOfWork、Postgresを使ってNancyアプリを実行しています。ナンシーはTinyIoCをIoCコンテナとして使用しています。
私はフロントエンドでリクエストを待ち行列に入れて、バックエンドに一度に1つのリクエストが当たるようにするWebアプリケーションを持っています。これはすべて正常に動作します。
しかし、同じバックエンドに接続し、バックエンドに要求をキューイングしない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...
}
私はこれがマルチであることを感じています2つの別々の要求が物事を爆発させる同じDbContext(または基本的な接続)を使用していることを示しています。
ナンシーブートストラップのConfigureRequestContainer
メソッドに依存関係を登録しようとしましたが、これは 'Connection is not open`例外をスローします。
この問題の背後にある理論は、この記事では明確に説明されていますhttp://mehdi.me/ambient-dbcontext-in-ef6/
次は私には不明である:
- は、私は、これはマルチスレッドの問題であると仮定して修正するのですか?
- 各リクエストが独自のDbContext /接続を使用するようにするためには、TinyIoC/Nancyを使用してDbContextのライフサイクルを管理するために、物事が衝突しないようにする必要があります。
これは複雑な問題であると私は理解しています。追加情報が必要な場合はお知らせください。
ありがとう:-)。
はい、単一のDbContextが複数のスレッドで使用されている可能性があります。要求ごとに新しいインスタンスとしてコンテナにDbContextを登録します。これにより、新しいインスタンスが解決されるたびに新しいインスタンスが作成されます。 – Evk
DbContextを次のように登録します: 'container.Register();' TinyIoCドキュメントを正しく理解すると、DbContextとマルチインスタンスが登録され、解決されるたびに新しいインスタンスが生成されます。これは私が現時点でどのように設定したのか、上記の状況を引き起こす原因です。つまり、マルチインスタンスであっても、リクエストごとに新しいインスタンスが保証されるわけではありません。 –
Corstiaan
いいえ、デフォルトではシングルトンとしてインターフェイスが登録されるため、毎回同じインスタンスが返されるため、問題が発生します。コンテナを作成します。()。AsMultiInstance()をマルチインスタンスとして登録します。 –
Evk