#c# #entity-framework #async-await
#c# #entity-framework #async-ожидание
Вопрос:
Этот пост в контексте использования 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.Resu<
int count2 = tcount2.Resu<
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 могут возникнуть проблемы с этой структурой?? Надеюсь, это просто мое невежество создает такое чувство.
Также следует отметить, что изначально я перезаписал сервис с использованием контекста в качестве поля класса service; однако в итоге я получил сообщение об ошибке:
Вторая операция, запущенная в этом контексте до завершения предыдущей асинхронной операции. Используйте ‘await’, чтобы убедиться, что все асинхронные операции завершены, прежде чем вызывать другой метод в этом контексте. Потокобезопасность любых членов экземпляра не гарантируется.
Изменение жизненного цикла контекста на вызовы метода исправило это, но, увидев эту ошибку в целом, я занервничал из-за этой общей стратегии.
Ответ №1:
На мой взгляд, вы делаете это правильно,
- Вам не следует кэшировать a
DbContext
, соединения sql кэшируются для вас уже под капотом. Это может привести к всевозможным незначительным ошибкам, с которыми вы уже сталкивались. - Контексты не являются потокобезопасными.
- Они довольно легкие, поэтому производительность на самом деле не должна вызывать беспокойства.
- И лучше всего помещаются в инструкцию using с небольшими пакетами работы
В целом, размещение каждого из них GetCount
кажется наилучшим подходом