Как оператор использования помогает предотвратить ZombieCheck () - PullRequest
0 голосов
/ 21 июня 2019

Я получаю эту ошибку, когда один вызов API в моем веб-API EF Core C # выполняется быстро.

Proj> System.InvalidOperationException: This SqlTransaction has completed; it is no longer usable.
Proj>    at System.Data.SqlClient.SqlTransaction.ZombieCheck()

Похоже, что решение заключается в следующем:

  1. Удалите соединение, используя оператор using c # corner link
  2. Измените AddDbContext на AddDbContextPool на основе этого сообщения SO

Как оператор using для контекста только для чтения помогает предотвратить приведенную ниже ошибку? Кажется нелогичным не звонить new MyContext()

public class MyController : Controller
{
    private readonly MyContext _mc;

    public GreenCardController(MyContext mc){_mc=mc;}

    [HttpGet("GetCompanies")]
    public IEnumerable<vwCompany> GetCompanies(int lgid)
    {
        using (MeSeeksContext mc = _mc){
          return mc.myTable.Where(x=>x.id==lgid)
        }
     }

1 Ответ

0 голосов
/ 21 июня 2019

Вы получаете контекст вашей базы данных извне контроллера через его конструктор. Если вы хотите использовать этот шаблон, сделайте так, чтобы внешний вызывающий отвечал за удаление контекста, когда закончите. Не используйте ключевое слово using при использовании этой стратегии.

В частности, вы получаете сообщение об ошибке, потому что возвращаемый вами IEnumerable оценивается лениво (то есть он не оценивается до тех пор, пока не будет необходим). Вызывающий код не может перебирать IEnumerable до тех пор, пока mc не будет удален из-за выхода из области действия оператора using.

Одно из решений состоит в том, чтобы метод создал свой собственный контекст и материализовал ответ перед его возвратом. Это хорошо работает, когда общее количество возвращаемых объектов довольно мало и может быть достигнуто путем добавления .ToList() после вызова.

using (MeSeeksContext mc = new MeSeeksContext() ){
    return mc.myTable.Where(x=>x.id==lgid).ToList();
}

Если вы возвращаете большое количество элементов, вы можете правильно следовать шаблону получения экземпляра контроллера от вызывающей стороны (альтернативно, вы можете выделить его как поле контроллера и убедиться, что он удаляется при экземпляре контроллера утилизируется). Если вы идете по этому пути, не используйте в своем методе оператор using. Используйте _mc

return _mc.myTable.Where(x=>x.id==lgid);
...