C# 在控制器中为多线程创建EF Core DBContext?
在我的一个控制器中,我有一个异步方法,必须同时进行几个db调用,因此我将其设置为:C# 在控制器中为多线程创建EF Core DBContext?,c#,entity-framework-core,C#,Entity Framework Core,在我的一个控制器中,我有一个异步方法,必须同时进行几个db调用,因此我将其设置为: public xxxController(IConfiguration configuration, xxxContext xxxContext, xxx2Context xxx2Context) : base(xxxContext) 我存储注入的上下文。在特定方法中: var v = await Task.WhenAll(... ) 在WhenAll内部,我需要为每个项目使用xxxContext,因此
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);
var v=new DbContextOptionsBuilder();
v、 使用SQLServer(_xxxContext.Database.GetDbConnection().ConnectionString);
xxContext e=新xxContext(v.选项);
因此,我从已注入的现有上下文中获取连接字符串,并使用该字符串创建一个新的连接字符串
连接字符串存储在appSettings.json中。在“连接字符串”部分
有没有更干净的方法来创建多线程上下文?为此,我创建了类似factory类的东西,它可以为每次调用提供上下文。就你的情况而言,可能是
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>();
}
}
您可以在上查看我的方法,恐怕您是这样执行异步方法的
var task = Task.Run(() => MyAsynchronosMethod());
DbContext
操作是输入输出操作,您无需在不同的线程上执行它们即可“同时”工作。您可以在没有新线程的情况下让它工作
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);
}
public MyController(IConfiguration配置、AContext AContext、BContext BContext)
:base(文本)
{
_aContext=aContext;
_b上下文=b上下文;
}
公共任务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};
等待任务。WhenAll(所有任务);
//用完成任务的结果做一些事情
返回OK(calculatedResult);
}
在上面的方法中,您将几乎同时发送所有查询,而无需等待响应。只有在发送了所有查询之后,您才开始等待响应。在所有查询结果到达后,您可以处理数据-所有操作都将在一个线程上执行。我需要在任何地方调用
createxxxContedeCurrentThread()
吗?您只需要在您自己创建的线程中调用它。否则,最好使用标准解析方法。(别忘了处理scopeResolver。出于简单的原因,我没有在回答时提到它)
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);
}