【问题标题】:When does EF Core DBContext dispose Sql Connection?EF Core DBContext 何时处理 Sql Connection?
【发布时间】:2021-10-06 03:51:35
【问题描述】:

在使用经典 ADO.NET 时,我们通常会在执行完 SQL 命令后立即关闭 SQL 连接,因此连接会关闭并返回到池中。

类似:

public Order[] GetActiveOrders()
{
        var orders = new List<Orders>();

        using (SqlConnection connection = new SqlConnection("connectionString"))
        {
            using (SqlCommand cmd = connection.CreateCommand())
            {
                cmd.CommandType = System.Data.CommandType.Text;
                cmd.CommandText = "Select * FROM ORDERS WHERE Status = 'Active'";
                cmd.Connection.Open();

                using (var reader = cmd.ExecuteReader())
                {
                    //populate orders
                }
            }
        }
        
        // SQL connection is closed here and returned back to connection pool
        
        return orders;
}

在使用 EF Core 的 ASP.NET Core 中,我们通常使用 DI 框架将DbContext 注入到构造函数中

      public class OrderService:IDisposable
      {
         private readonly MyDBContext _dbContext;
         
         public OrderService(MyDBContext dbContext)
         {
             _dbContext = dbContext;
         }
         
         public Order[] GetActiveOrders()
         {
             var orders = _dbContext.Orders.Where(x=>x.Status == 'Active').ToArray()
             return orders;
         }
         
         #region Dispose
         public void Dispose()
         {
              Dispose(true);
              GC.SuppressFinalize(this);
         }
    
         protected virtual void Dispose(bool disposing)
         {
              if (_disposed)
                  return;

              if (disposing)
              {
                  if (_dbContext != null)
                  {
                      _dbContext.Dispose();
                  }

                  // Free any other managed objects here.                    
              }

              // Free any unmanaged objects here.
              _disposed = true;
          }
      }
      

我假设在后台,DbContext 仍在使用SqlCommandSqlConnection 连接到数据库。

我想知道 EF Core 什么时候关闭SqlConnection?它会在执行完查询后立即关闭连接(就像我们在经典 ADO 中所做的那样)还是在释放 DbContext 时关闭连接?

那么在上面的例子中,它会在GetActiveOrders()方法返回Orders之前或者当OrderService被DI容器释放时释放连接?

【问题讨论】:

  • 一般服务不应该释放它不拥有的资源,即通过ctor注入的任何依赖。

标签: c# asp.net-core entity-framework-core dbcontext sqlconnection


【解决方案1】:

旁注:您不应该处置您不拥有的东西,DI 注入 DbContext(以及任何注入的对象)就是这种情况。

但是要回答你具体的问题。我找不到要链接的文档,但只要你

  • 不要通过DbContextOptions提供预分配的DbConnection对象
  • 不要通过.Database.OpenConnection方法手动打开连接
  • 不要通过Database.BeginTransaction 方法打开显式事务

即不要自己进行一些连接管理(在这种情况下您负责关闭/处置),EF Core 仅在需要时打开连接并在此之后立即关闭它。

当需要时意味着在SaveChanges 期间打开一个事务,直到它被提交或回滚。或者在执行DbReader返回查询时,直到返回的阅读器被消耗或取消。换句话说,您将如何使用经典的 ADO.NET 来完成它。是的,它在幕后使用 ADO.NET(至少对于关系数据库而言)。

这里有一些附加信息Do I need to close the DbConnection manually when using ambient transactions with EF Core 2.1?Using EF Core to invoke stored procedure and closing connection。还有Connection ResiliencyHow queries work 文档主题。

【讨论】:

  • 所以连接应该在 GetActiveOrders() 返回给调用者之前处理掉?
  • 在您的示例中,它将在ToArray 方法调用传递的IQueryableGetEnumerator().MoveNext()(查询执行点)时打开。并将在ToArray() 完成后立即关闭它(完成使用返回的DbReader)。处理呢,我不确定,肯定会关闭,这应该将物理连接返回到池。
  • EF Core 内部代码与stackoverflow.com/questions/57283317/… 类似,但有更多检查,并且在ExecuteReader 的情况下关闭打开的阅读器之前不要调用close。所以没有Dispose,但它不是必需的。
猜你喜欢
  • 2021-01-21
  • 1970-01-01
  • 2018-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-02
  • 2018-08-05
  • 2019-04-30
相关资源
最近更新 更多