在我的一个控制器中,我有一个异步方法,必须同时进行几个db调用,所以我这样设置:
+---------+----------+------------+------+
| item_id | order_id | product_id | qty |
+---------+----------+------------+------+
| 15329 | 7369 | 18253 | 3 | // 3
| 15330 | 7370 | 18253 | 1 | // 4
| 15331 | 7371 | 18253 | 7 | // 11
| 15332 | 7372 | 18253 | 1 | // 12
| 15333 | 7373 | 18253 | 1 | // 13
+---------+----------+------------+------+
我存储了注入的上下文。在特定方法中:
public xxxController(IConfiguration configuration, xxxContext xxxContext, xxx2Context xxx2Context)
: base(xxxContext)
在WhenAll内部,我需要为每个项使用xxxContext,因此我得到了非线程安全异常。
创建新DbContext的正确方法是什么?现在我正在做:
var v = await Task.WhenAll(... )
所以我从注入的现有上下文中获取连接字符串,并使用它来创建一个新的连接字符串。
连接字符串存储在appSettings.json中。在" ConnectionStrings"部分。
是否有更简洁的方法来创建多线程的上下文?
答案 0 :(得分:0)
为此,我创建了类似工厂类的东西,它可以为每次调用提供上下文。对于你的情况,它可以是
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>();
}
}
比你应该在Startup中调用Init
方法
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
AppDependencyResolver.Init(app.ApplicationServices);
//other configure code
}
您可以在github
上查看我的方法答案 1 :(得分:-1)
我害怕以这种方式执行异步方法
var task = Task.Run(() => MyAsynchronosMethod());
DbContext
操作是输入输出操作,您不需要在不同的线程上执行它们同时工作&#34;。你可以在没有新线程的情况下使它工作。
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);
}
在上面的方法中,您几乎可以同时发送所有查询,而无需等待响应。只有在发送所有查询后才开始等待响应 在所有查询结果到达后,您可以处理数据 - 所有操作都将在一个线程上执行。