gpt4 book ai didi

c# - EF 7(核心)。像 AddTransient 一样创建 DBContext

转载 作者:行者123 更新时间:2023-11-30 18:46:00 25 4
gpt4 key购买 nike

根据文档,当我像下面这样配置 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();
}
}

我想为每次调用 (AddTransition) 配置 DbContext 创建。这将使我有可能编写下一个代码

    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 ,当我想在某些后台线程中使用 DBContext 时,我可以使用 IUnitOfWorkFactoryPerCall .

最佳答案

我的临时解决方案。我创建了可以“以 transient 方式”创建上下文的单例

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()

如果有人能提供更优雅的解决方案,我将不胜感激。

关于c# - EF 7(核心)。像 AddTransient 一样创建 DBContext,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34952087/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com