【问题标题】:Creating a transaction scope with new SqlConnection within existing SqlConnection using block使用块在现有 SqlConnection 中创建具有新 SqlConnection 的事务范围
【发布时间】:2013-05-31 10:21:07
【问题描述】:

我想执行单个 SELECT 查询,然后执行一系列 UPDATE 查询(都在同一张表上); UPDATE 是在一个单独的方法中实现的,该方法被重复调用。如果其中一个 UPDATE 查询失败,我希望它们全部失败/回滚 - 所以我想将它们加入事务。但是,我不确定应该在哪里打开 SqlConnection 以避免任何问题。我当前的实现如下所示:

using (SqlConnection connection = new SqlConnection(connectionString))
{
    connection.Open();

    // execute a single SELECT here

    using (TransactionScope scope = new TransactionScope())
    {
        for (int i=0; i<...; i++)
        {
            Update(); // UPDATE query
        }

        scope.Complete();
    }
}


Update()
{
    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        connection.Open();

        // execute a single UPDATE here
    }
}

在所有情况下都应该按预期工作吗?

SELECT之前打开一个连接,然后用Update()方法打开一个新连接可以吗?由于连接池,SELECT 和 UPDATE 查询将使用相同的连接(connectionString 相同),但事务中只会加入 UPDATE 查询,对吗?但是如果在Update() 中使用不同的连接会发生什么?所有 UPDATE 查询是否仍会按预期加入事务并自动执行?

如果我理解正确,在关闭第一个连接后(在执行 SELECT 的 using 块之后)创建事务范围仍然有效,但会降低性能,因为连接将被关闭并需要重新打开, 正确的?或者实际上是为事务范围创建了一个新连接,并且每次调用Update() 时都会打开和关闭?

【问题讨论】:

    标签: c# .net sql transactionscope


    【解决方案1】:

    由于连接池,同一连接将用于 SELECT 和 UPDATE 查询

    不,它不会;只有当您首先将连接释放回池中时,它才能做到这一点 - 目前您同时有两个连接,所以它不可能是同一件事。你需要稍微重组一下:

    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        connection.Open();
    
        // execute a single SELECT here
    } // <==== end the first connection
    
    using (TransactionScope scope = new TransactionScope())
    {
        for (int i=0; i<...; i++)
        {
            Update(); // UPDATE query
        }
    
        scope.Complete();
    }
    

    在关闭第一个连接后创建事务范围 (...) 但会降低性能,因为连接将被关闭并需要重新打开,正确

    没有;当你“关闭”它时,你实际上只是将它释放回池中;它不会关闭底层连接(除非您禁用了池)。关闭(或至少,丢弃)是正常的和预期的。

    但只有 UPDATE 查询会被纳入事务,对吧?

    正确,因为那只是在事务范围内打开连接的地方

    但是如果在 Update() 中使用了不同的连接会发生什么?所有 UPDATE 查询是否仍会按预期加入事务并自动执行?

    任何支持登记的连接(假设它没有在连接字符串中被禁用)都将被登记。但是,根据服务器的不同,这可能使用 LTM 或可能使用 DTC。如果你想确定你的关系:控制他们:

    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        connection.Open();
    
        // execute a single SELECT here
    } // <==== end the first connection
    
    using (TransactionScope scope = new TransactionScope())
    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        connection.Open();
        for (int i=0; i<...; i++)
        {
            Update(connection); // UPDATE query
        }
    
        scope.Complete();
    }
    

    注意我在上面将connection 传递给Update;这里很明显将使用单个连接(假设Update 正常工作)。

    【讨论】:

    • @w128 note 我编辑了几次;确保您已刷新以查看最新版本
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-05
    • 1970-01-01
    • 1970-01-01
    • 2010-10-27
    • 2011-12-23
    相关资源
    最近更新 更多