0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ASP.NET Core のStartup.csのConfigureメソッド内でDBを使うとき

Posted at

経緯

 StartupのConfigureの処理中に、DBの内容を参照したい。
 具体的には初回起動時にDBのシステム設定のテーブルが空なら、初期設定画面に強制遷移したい。その為にDBが見たかったのですが、ちょっと引っかかってしまったので、備忘録として書いときます。
 まあ、引っかかってる人がいれば参考になるか、もっといい方法があるぞとか教えてください。

実装

 Startup.csでDBが以下の様に登録されている場合。(Npgsqlになっているのはご愛嬌)

Startup.cs

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseNpgsql(
                    Configuration.GetConnectionString("DefaultConnection")));
        ...
        }

 同じくStartup.csのConfigureメソッドでDIを利用して以下のように記述して使おうとすると

Startup.cs
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ApplicationDbContext dbContext)
        {
            if(dbContext.Settings.Count() == 0)
            {
                // 初期設定できてないので初期設定画面を表示
                context.Response.Redirect("/Initialize");
                return;
            }
        ...
        }

 実行時に以下のようなエラーメッセージが表示されてしまいます。

ObjectDisposedException: Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling Dispose() on the context, or wrapping the context in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.
Object name: 'ApplicationDbContext'.

 オブジェクトはありそうですが、中のDB接続が破棄されてるみたいです。
 引数「IApplicationBuilder app」から取得する必要がありそうですが、なかなかそういった記事が見当たらないので試してみたところ、

Startup.cs
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            var dbContext = app.ApplicationServices.CreateScope().ServiceProvider.GetRequiredService<ApplicationDbContext>();

            if(dbContext.Settings.Count() == 0)
            {
                // 初期設定できてないので初期設定画面を表示
                context.Response.Redirect("/Initialize");
                return;
            }
        ...
        }

 とするとうまくいきました。
 分りにくかったのは、app.ApplicationServicesにも「GetRequiredService<>」メソッドがあるのですがこちらでは取得できません。上記の様にスコープを作ってそこのサービスから取得しないといけない様です。

 とりあえずこれでできたのいいのですが、こうすべきというやり方があればコメントください。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?