Список синхронных запросов dbcontext, переписанных как асинхронные вызовы в отдельных контекстах

#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:

На мой взгляд, вы делаете это правильно,

  1. Вам не следует кэшировать a DbContext , соединения sql кэшируются для вас уже под капотом. Это может привести к всевозможным незначительным ошибкам, с которыми вы уже сталкивались.
  2. Контексты не являются потокобезопасными.
  3. Они довольно легкие, поэтому производительность на самом деле не должна вызывать беспокойства.
  4. И лучше всего помещаются в инструкцию using с небольшими пакетами работы

В целом, размещение каждого из них GetCount кажется наилучшим подходом