[英]Create EF Core DBContext in controller for multi-threading?
在我的一个控制器中,我有一个异步方法,该方法必须同时进行几个数据库调用,因此我将其设置如下:
public xxxController(IConfiguration configuration, xxxContext xxxContext, xxx2Context xxx2Context)
: base(xxxContext)
我存储注入的上下文。 在特定方法中:
var v = await Task.WhenAll(... )
在WhenAll内部,我需要为每个项目使用xxxContext,因此我得到了非线程安全的异常。
创建新的DbContext的正确方法是什么? 现在我正在做:
var v = new DbContextOptionsBuilder<xxxContext>();
v.UseSqlServer(_xxxContext.Database.GetDbConnection().ConnectionString);
xxContext e = new xxContext(v.Options);
因此,我从注入的现有上下文中获取连接字符串,并使用该字符串创建一个新字符串。
连接字符串存储在appSettings.json中。 在“ ConnectionStrings”部分。
有没有更干净的方法来创建多线程上下文?
为此,我创建了一些类似于工厂类的东西,它可以为每个调用提供上下文。 对于你的情况可以
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;
private AppDependencyResolver(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public xxxContext CreatexxxContextinCurrentThread()
{
var scopeResolver = _serviceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope();
return scopeResolver.ServiceProvider.GetRequiredService<xxxContext>();
}
}
比您应该在启动中调用Init
方法
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
AppDependencyResolver.Init(app.ApplicationServices);
//other configure code
}
您可以在github上查看我的方法
恐怕您以这种方式执行异步方法
var task = Task.Run(() => MyAsynchronosMethod());
DbContext
操作是Input-Output操作,您无需在其他线程上执行它们即可“同时”工作。 您可以在没有新线程的情况下使它工作。
public MyController(IConfiguration configuration, AContext aContext, BContext bContext)
: base(aContext)
{
_aContext = aContext;
_bContext = bContext;
}
public Task<IActionResult> GetSomething(int id)
{
var customerTask = aContext.Customers
.FirstOrDefaultAsync(customer => customer.Id == id);
var sellerTask = aContext.Sellers
.FirstOrDefaultAsync(seller => seller.CustomerId == id);
var ordersTask = bContext.Orders
.Where(order => order.CustomerId == id)
.ToListAsync();
var invoicesTask = bContext.Invoices
.Where(invoice => invoice.CustomerId == id)
.ToListAsync();
var allTasks = new[] { customerTask, sellerTask, ordersTask, invoicesTask};
await Task.WhenAll(allTasks);
// Do stuff with result of completed tasks
Return OK(calculatedResult);
}
在上面的方法中,您几乎同时发送所有查询,而无需等待响应。 仅在发送所有查询之后,您才开始等待响应。
在所有查询结果到达后,您可以处理数据-所有操作将在一个线程上执行。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.