Этот пост в контексте использования Entity Framework версии 6.2.
Хорошо, у меня довольно медленная конечная точка, по сути, следующая:
public IHttpActionResult GetCounts()
{
int count1 = service.GetCount1();
int count2 = service.GetCount2();
Models.Counts ret = new Counts()
{
Count1 = count1,
Count2 = count2,
};
return Ok(ret);
}
каждый вызов службы выполняется в одном и том же экземпляре dbcontext:
//In the service
public class Service
{
private MyDbContext context;
public Service()
{
context = new MyDbContext();
}
public int GetCount1()
{
return context.coll1.Count();
}
public int GetCount2()
{
return context.coll2.Count();
}
}
было бы лучше обработать каждый сервисный вызов как отдельные единицы работы и создать контексты для каждого из них, а затем использовать асинхронные методы EF, как показано ниже:
public async Task<IHttpActionResult> GetCountsAsync()
{
var tcount1 = service.GetCount1Async();
var tcount2 = service.GetCount2Async();
await Task.WhenAll(tcount1, tcount2);
int count1 = tcount1.Result;
int count2 = tcount2.Result;
Models.Counts ret = new Counts()
{
Count1 = count1,
Count2 = count2
};
return Ok(ret);
}
с изменениями в услуге
//In the service
public class Service
{
public Service()
{
}
public async Task<int> GetCount1()
{
using(var context = new MyDbContext())
{
return await context.coll1.CountAsync();
}
}
public async Task<int> GetCount2()
{
using(var context = new MyDbContext())
{
return await context.coll2.CountAsync();
}
}
}
Есть ли минусы в этом? Это работает и определенно улучшило производительность запроса.
Я довольно плохо знаком с потоками (в данном случае async / wait), поэтому незнаком с потенциальными недостатками или если то, что у меня есть выше, является антипаттерном, но часть меня чувствует, что могут быть проблемы с этой структурой при использовании dbcontext EF ?? Надеюсь, это просто мое невежество, создающее это чувство.
Также отметим, что сначала я переписывал сервис с контекстом как полем класса сервиса; тем не менее, в конечном итоге получил ошибку:
Вторая операция началась в этом контексте до завершения предыдущей асинхронной операции. Используйте 'await', чтобы убедиться, что все асинхронные операции завершены, прежде чем вызывать другой метод в этом контексте. Любые члены экземпляра не гарантированно защищены от потоков.
Изменение жизненного цикла контекста на вызовы методов исправило это, но, видя эту ошибку в целом, я нервничал из-за этой общей стратегии.