using 语句如何帮助防止 ZombieCheck()

How does a using statement help prevent ZombieCheck()

当我的 EF Core C# web API 中的一个 API 调用被快速命中时,我收到此错误。

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

只读上下文的 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)
        }
     }

您通过控制器的构造函数从控制器外部接收数据库上下文。如果您想使用该模式,请让外部调用者负责在完成后处理上下文。遵循该策略时不要使用 using 关键字。

您特别收到错误消息,因为您 return 的 IEnumerable 被延迟求值(这意味着它在必要时才被求值)。在 mc 由于退出 using 语句的范围而被释放之前,调用代码没有机会迭代 IEnumerable。

一种解决方案是让方法实例化自己的上下文并在 returning 之前具体化响应。这在 returned 对象的总数相当小并且可以通过在调用后添加 .ToList() 来实现时效果很好。

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

如果您 return 大量项目,您可以正确地遵循从调用者接收控制器实例的模式(或者,您可以将其分配为控制器的一个字段并确保它当控制器实例被处置时被处置)。如果你走那条路,不要在你的方法中使用 using 语句。使用 _mc

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