【问题标题】:Do I need to close the DbConnection manually when using ambient transactions with EF Core 2.1?在 EF Core 2.1 中使用环境事务时是否需要手动关闭 DbConnection?
【发布时间】:2018-07-09 06:27:12
【问题描述】:

EF Core 2.1 引入了对环境事务的支持。 sample创建一个新的SqlConnection,手动打开并传递给DbContext

using (var scope = new TransactionScope(
    TransactionScopeOption.Required, 
    new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted }))
{
    var connection = new SqlConnection(connectionString);
    connection.Open();

    try
    {
        // Run raw ADO.NET command in the transaction
        var command = connection.CreateCommand();
        command.CommandText = "DELETE FROM dbo.Blogs";
        command.ExecuteNonQuery();

        // Run an EF Core command in the transaction
        var options = new DbContextOptionsBuilder<BloggingContext>()
            .UseSqlServer(connection)
            .Options;

        using (var context = new BloggingContext(options))
        {
            context.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/dotnet" });
            context.SaveChanges();
        }

        // Commit transaction if all commands succeed, transaction will auto-rollback
        // when disposed if either commands fails
        scope.Complete();
    }
    catch (System.Exception)
    {
        // TODO: Handle failure
    }
}

虽然没有给connection.Close()打电话。

这部分只是在示例中丢失,还是在处理TransactionScopeDbContext 时以某种方式自动关闭连接?

编辑:对 Close/Dispose 的调用丢失。我提交了拉取请求,文档现已更新。

【问题讨论】:

  • 您必须对其进行测试,例如使用 SQL Server Profiler - 必须在 内部 一个事务中创建一个连接才能自动登记。否则你必须显式调用Enlist()。在事务本身提交之前连接不能关闭,否则提交/回滚将是不可能的。 也许当 TransactionScope 超出范围时,一些魔术代码负责实际关闭连接。不过,Maybes 并不适合数据访问代码
  • 这就是我来这里询问的原因。
  • 我会避免这样的代码。即使该魔法代码存在,您也必须确保在TransactionScope始终调用此代码以启用魔法。如果其他开发人员甚至您忘记了它,您将开始泄漏连接。
  • 使用需要在using块中调用context.Database.OpenConnection()context.Database.CloseConnection()

标签: c# entity-framework-core transactionscope


【解决方案1】:

该行为似乎与环境事务无关,但问题的答案谁拥有DbConnection 已传递给DbContext

EF6 DbContext 构造函数接受 DbConnection 具有 bool contextOwnsConnection 参数,用于明确指定。

但是 EF Core 怎么样?在接受DbConnectionUseXyz 方法上没有这样的参数。

规则好像如下,取自UseSqlServer方法connection参数文档:

如果连接处于打开状态,则 EF 不会打开或关闭连接。如果连接处于关闭状态,则 EF 将根据需要打开和关闭连接。

我读到“如果传递的连接没有打开,EF Core 将取得所有权,否则所有权留给调用者”

由于示例在UseSqlServer(connection) 之前调用connection.Open();,我假设您负责关闭/处置它,因此我认为示例不正确。

【讨论】:

  • 查看示例我得出了相同的结论。相当草率:(
【解决方案2】:

为了安全使用使用,以便处理连接。

using(var connection = new SqlConnection(connectionString)) {
   ....
}

【讨论】:

  • 谢谢,我不能使用 using,因为我的代码比示例更复杂。我的问题更多是关于我是否负责关闭连接,而不是关于如何关闭连接(如果是,为什么文档中的示例中缺少代码)。
  • 对不起,我的回答不切题。关于示例,连接被实例化并在 DbContext 和 Command 中使用。如果是 dbcontext 示例,则 db 创建并关闭连接。但是,上面的示例并非如此。必须手动关闭连接。即使垃圾收集器处理连接对象,我也不能 100% 确定与数据库的连接是否正确终止。读取限制后,数据库可能会拒绝额外的连接(取决于数据库的类型)。根据您的问题,我认为缺少关闭连接。
猜你喜欢
  • 1970-01-01
  • 2021-08-17
  • 2012-08-15
  • 1970-01-01
  • 1970-01-01
  • 2010-10-19
  • 2011-04-10
  • 1970-01-01
  • 2018-12-17
相关资源
最近更新 更多