簡體   English   中英

EF 7(核心)。 像AddTransient一樣創建DBContext

[英]EF 7 (Core). Create DBContext like AddTransient

根據文檔,我在下面配置DbContext時,DI在范圍內注冊(每個http請求)

services.AddEntityFramework()
   .AddSqlServer()
   .AddDbContext<DBData>(options => {
        options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]);                    
    }
);

當我嘗試在另一個線程中訪問它時出現問題。

public class HomeController : Controller
{
    private readonly DBData _context;

    public HomeController(DBData context)
    {
        _context = context;
    }

    public IActionResult StartInBackground()
    {
        Task.Run(() =>
            {
                Thread.Sleep(3000);
                //System.ObjectDisposedException here
                var res = _context.Users.FirstOrDefault(x => x.Id == 1);
            });

        return View();
    }
}

我想為每個調用配置DbContext創建(AddTransition)。 它可以讓我編寫下一個代碼

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddEntityFramework()
            .AddSqlServer()
            .AddDbContext<DBData>(options => {
                //somehow configure it to use AddTransient
                options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]);                    
                }
            );

        services.AddTransient<IUnitOfWorkFactoryPerCall, UnitOfWorkFactory>();
        services.AddScoped<IUnitOfWorkFactoryPerRequest, UnitOfWorkFactory>();

        services.AddMvc();
    }

    public interface IUnitOfWorkFactoryPerCall : IUnitOfWorkFactory { }
    public interface IUnitOfWorkFactoryPerRequest : IUnitOfWorkFactory { }

    public interface IUnitOfWorkFactory : IDisposable
    {
       DBData Context { get; }
    }

    public class UnitOfWorkFactory : IUnitOfWorkFactoryPerCall, IUnitOfWorkFactoryPerRequest
    {
        public UnitOfWorkFactory(DBData context)
        {
            Context = context;
        }

        public DBData Context
        {
            get; private set;
        }

        public void Dispose()
        {
            Context.Dispose();
        }
    }

所以現在如果我想為每個請求創建DBContext,我將使用IUnitOfWorkFactoryPerRequest ,當我想在某些后台線程中使用IUnitOfWorkFactoryPerCall我可以使用IUnitOfWorkFactoryPerCall

我的臨時解決方案 我創建了單例,它可以“以瞬態方式”創建上下文

public class AppDependencyResolver
{
    private static AppDependencyResolver _resolver;

    public static AppDependencyResolver Current
    {
        get
        {
            if (_resolver == null)
                throw new Exception("AppDependencyResolver not initialized. You should initialize it in Startup class");
            return _resolver;
        }
    }

    public static void Init(IServiceProvider services)
    {
        _resolver = new AppDependencyResolver(services);
    }

    private readonly IServiceProvider _serviceProvider;

    public AppDependencyResolver(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public IUnitOfWorkFactory CreateUoWinCurrentThread()
    {
        var scopeResolver = _serviceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope();
        return new UnitOfWorkFactory(scopeResolver.ServiceProvider.GetRequiredService<DBData>(), scopeResolver);
    }
}

然后我在Startup Configure方法中調用init方法

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    AppDependencyResolver.Init(app.ApplicationServices);
    //other configure code
}

畢竟我可以在一些后台線程中調用AppDependencyResolver.Current.CreateUoWinCurrentThread()

如果有人能提供更優雅的解決方案,我將不勝感激。

在你的控制器中,你為什么要嘗試注入private readonly DBData _context; 如果您已經通過DI注冊了IUnitOfWorkFactoryPerCall ,那么您應該將其注入您的控制器嗎? 然后,您可以通過界面訪問您的上下文。

為了擴展,我建議你這樣做:

public class HomeController : Controller
{
    private readonly IUnitOfWorkFactoryPerCall _contextFactory;

    public HomeController(IUnitOfWorkFactoryPerCall contextFactory)
    {
        _contextFactory = contextFactory;
    }

    public IActionResult StartInBackground()
    {
        Task.Run(() =>
            {
                Thread.Sleep(3000);
                //System.ObjectDisposedException here
                var res = _contextFactory.Context.Users.FirstOrDefault(x => x.Id == 1);
            });

        return View();
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM