代码之家  ›  专栏  ›  技术社区  ›  Johan Danforth

实体框架上下文是否应放入using语句中?

  •  62
  • Johan Danforth  · 技术社区  · 15 年前

    实体框架上下文对象实现Dispose()方法,该方法“释放对象上下文使用的资源”。它真的有什么作用?总是把它放在using语句中会是一件坏事吗?我已经看到它在使用和不使用using语句的情况下都被使用。

    我将专门使用wcf服务方法中的ef上下文,创建上下文,执行一些linq并返回答案。

    编辑: 似乎我不是唯一一个对此感到疑惑的人。另一个问题是Dispose()方法中到底发生了什么。有人说它关闭了连接,还有一些文章说不是。怎么回事?

    9 回复  |  直到 10 年前
        1
  •  33
  •   Daniel Brückner    15 年前

    如果创建一个上下文,则必须稍后释放它。如果你应该使用 using 语句取决于上下文的生命周期。

    1. 如果您在一个方法中创建上下文,并且只在这个方法中使用它,那么您应该真正使用 使用 语句,因为它不需要任何附加代码就可以为您提供异常处理。

    2. 如果使用上下文的时间较长(即生命周期不受方法执行时间的限制),则不能使用 使用 你必须打电话 Dispose() 你自己,小心你总是叫它。

    什么? 处置() 对对象上下文执行此操作?

    我没有查看代码,但至少我检查了它,以关闭数据库连接及其底层套接字或传输机制使用的任何资源。

        2
  •  4
  •   ullmark    15 年前

    由于您不知道垃圾收集器何时处理某个项,所以最好将实现IDisposable的对象包装在 使用块 如果你知道什么时候结束。

        3
  •  4
  •   Cory House    14 年前

    Progamming Entity Framework :“您可以显式地释放ObjectContext或等待垃圾回收器执行该作业。”

    因此,简而言之,虽然不需要using语句,但如果您知道已经使用了objectcontext,这是最佳实践,因为资源将立即释放,而不是等待垃圾收集。

        4
  •  3
  •   Tieson T.    10 年前

    EF5及之前版本

        using { ...
                // connecction open here.
    
                ...
                context.Blogs.Add(blog); 
                context.SaveChanges();   // query etc now opens and immediately closes 
    
                ...
                context.Blogs.Add(blog); 
                context.SaveChanges();   // query etc now opens and immediately closes 
       }
    

    EF6及之后版本

     using {
            // connecction open here.
    
            ...
            context.Blogs.Add(blog); 
            context.SaveChanges(); 
    
            // The underlying store connection remains open for the next operation  
    
            ...
            context.Blogs.Add(blog); 
            context.SaveChanges(); 
    
            // The underlying store connection is still open 
    
       } // The context is disposed – so now the underlying store connection is closed
    

    参考文献: http://msdn.microsoft.com/en-us/data/dn456849#open5

        5
  •  1
  •   John Saunders    15 年前

    始终,如果实例化实现IDisposable的类,则负责对其调用Dispose。除一种情况外,这意味着 使用 块。

        6
  •  1
  •   Alex James    15 年前

    处理时,ObjectContext会处理其他拥有的对象。

    包括像EntityConnection这样的东西,它包装了实际的数据库连接,即通常是一个sqlConnection。

    因此,如果“sqlconnection”打开,则在释放objectcontext时将关闭它。

        7
  •  1
  •   Artem A    11 年前

    我真的在ado.net和ef v.6中测试了这个东西,并在SQL表中观察了连接。

    select * from sys.dm_exec_connections
    

    测试方法如下:

    1)使用ADO.NET

      using(var Connection = new SqlConnection(conString))
      {
        using (var command = new SqlCommand(queryString, Connection))
        {    
           Connection.Open();
           command.ExecuteNonQueryReader();
           throw new Exception()  // Connections were closed after unit-test had been 
           //finished.  Expected behaviour
         }
      }
    

    2)使用ADO.NET

    var Connection = new SqlConnection(conString);
    using (var command = new SqlCommand(queryString, Connection))
    {
        Connection.Open();
         command.ExecuteNonQueryReader();
        throw new Exception() // Connections were NOT closed after unit-test had been finished
    
         finished.  I closed them manually via SQL.  Expected behaviour
        }
    

    1)EF与使用。

     using (var ctx = new TestDBContext())
        {
            ctx.Items.Add(item);
            ctx.SaveChanges();
            throw new Exception() // Connections were closed, as expected.
    
         }
    

    2)不使用EF

     var ctx = new TestDBContext();             
     ctx.Items.Add(item);
     ctx.SaveChanges();
     throw new Exception() // Connections WERE successfully closed, as NOT expected.
    

    我不知道为什么会这样,但EF自动关闭了连接。另外,所有使用EF的存储库和UnitOfWork模式都不使用using。这对我来说很奇怪,因为dbContext是一次性类型,但这是事实。

    也许在微软他们做了一些新的处理?

        8
  •  0
  •   Lewis Tatham    12 年前

    我注意到(虽然只有一个应用程序)显式处理导致mscorlib中的线程中止异常,这些异常在应用程序代码之前被捕获,但至少在我的情况下,会导致明显的性能损失。还没有对这个问题做过任何重要的研究,但是如果你这样做的话,可能有一些值得考虑的事情。只需观察调试输出,看看是否得到相同的结果。

        9
  •  0
  •   Ilya    11 年前

    如果Dispose关闭与DB的连接,则不建议调用它。 例如,在ADO.NET中,连接位于连接池中,并且在超时或应用程序池停止之前永远不会关闭。