ASP.NET Core 使用 AutoFac 注入 DbContext


DI 1.0 —— 通過 RegisterInstance 注入

一開始,並不是很懂 AutoFac 的用法,又因為要使用特定的構造器和參數來初始化 DbContext,所以我想到的辦法就是使用 RegisterInstance,代碼如下:

var optionsBuilder = new DbContextOptionsBuilder<BookListDbContext>();
optionsBuilder.UseMySql(connectionString, b => b.MigrationsAssembly("BookList.Domain"));
// SingleInstance 就是單例模式,現在想起來當時寫的好智障
containerBuilder.RegisterInstance(new BookListDbContext(optionsBuilder.Options)).SingleInstance();

一開始在本地用 Swagger 一個一個的調試 api 的感覺還很好,沒啥問題,后來前端同學把 js 加上,就會經常的出現 404。經過 debug 發現,是 DbContext 出現了沖突,多個請求同時訪問同一個 DbContext 對象,造成異常,雖然不清楚為啥沒有出現500而是404。

DI 2.0 —— 添加 IDbContext 接口,通過 RegisterType 注入

知道了問題所在,就想到了更換服務的生命周期設置,於是我在上面的代碼的基礎上直接把 SingleInstance 改成了 InstancePerLifetimeScope,但在運行時遇到了異常,原來 RegisterInstance 僅支持 SingleInstance。既然這樣,那就接着換,於是我在網上發現了別人通過讓自定義的 DbContext 實現一個 IDbContext 接口,進行依賴注入,代碼如下:

// ··········· 省略 IDbContext 的定義
var optionsBuilder = new DbContextOptionsBuilder<BookListDbContext>();
optionsBuilder.UseMySql(connectionString, b => b.MigrationsAssembly("BookList.Domain"));
containerBuilder.RegisterType<MyDbContext>()
    .As<IDbContext>()
    .WithParam("options",optionsBuilder.Options)
    .InstancePerLifetimeScope();

這樣一來,我們就需要提取一個 IDbContext ,這個工作有些麻煩,但是在 ReSharper 的幫助下,簡化了不少。然而,這個方法並沒有生效,現在消費者類依賴 IDbContext 接口的一個實例,但是在實例化服務的時候卻拋出了異常。。。
很蛋疼,剛剛提取出來的接口白費了。

DI 3.0 —— 使用 Register 方法

其實這個是我根據 Intellisence 試出來的,代碼如下:

// 首先注冊 options,供 DbContext 服務初始化使用
containerBuilder.Register(c =>
{
    var optionsBuilder = new DbContextOptionsBuilder<BookListDbContext>();
    optionsBuilder.UseMySql(connectionString, b => b
        .MigrationsAssembly("BookList.Domain"));
    return optionsBuilder.Options;
}).InstancePerLifetimeScope();
// 注冊 DbContext
containerBuilder.RegisterType<BookListDbContext>()
    .AsSelf()
    .InstancePerLifetimeScope();

實驗證明,這樣注入 DbContext 是沒有問題的


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM