使用块在现有SqlConnection中使用新SqlConnection创建事务作用域

w12*_*128 3 .net c# sql transactionscope

我想执行一个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
    }
}
Run Code Online (Sandbox Code Playgroud)

在所有情况下这应该如预期的那样工作吗

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

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

Mar*_*ell 8

由于连接池,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();
}
Run Code Online (Sandbox Code Playgroud)

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

没有; 当你"关闭"它时,你实际上只是将它释放回游泳池; 它不会关闭底层连接(除非您禁用了池).关闭(或至少处置)是正常的和预期的.

但只有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();
}
Run Code Online (Sandbox Code Playgroud)

注意我正在connection进入Update上面; 这里很明显,将使用单个连接(假设Update工作正常).