使用block在现有SqlConnection中创建一个新的SqlConnection事务范围

本文关键字:SqlConnection 一个 范围 事务 block 创建 使用 | 更新日期: 2023-09-27 18:16:26

我想执行一个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()时都打开和关闭?

使用block在现有SqlConnection中创建一个新的SqlConnection事务范围

由于连接池,相同的连接将用于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正常工作)。