gpt4 book ai didi

c# - 在什么情况下 SqlConnection 会自动加入环境 TransactionScope 事务?

转载 作者:IT王子 更新时间:2023-10-29 03:29:45 25 4
gpt4 key购买 nike

SqlConnection 在事务中“登记”是什么意思?这是否只是意味着我在连接上执行的命令将参与事务?

如果是这样,在什么情况下 SqlConnection 会自动加入环境 TransactionScope 事务?

请参阅代码注释中的问题。我对每个问题的答案的猜测都在括号中的每个问题之后。

场景 1:在事务范围内打开连接

using (TransactionScope scope = new TransactionScope())
using (SqlConnection conn = ConnectToDB())
{
// Q1: Is connection automatically enlisted in transaction? (Yes?)
//
// Q2: If I open (and run commands on) a second connection now,
// with an identical connection string,
// what, if any, is the relationship of this second connection to the first?
//
// Q3: Will this second connection's automatic enlistment
// in the current transaction scope cause the transaction to be
// escalated to a distributed transaction? (Yes?)
}

场景 2:在事务范围内使用连接,而在事务范围外打开
//Assume no ambient transaction active now
SqlConnection new_or_existing_connection = ConnectToDB(); //or passed in as method parameter
using (TransactionScope scope = new TransactionScope())
{
// Connection was opened before transaction scope was created
// Q4: If I start executing commands on the connection now,
// will it automatically become enlisted in the current transaction scope? (No?)
//
// Q5: If not enlisted, will commands I execute on the connection now
// participate in the ambient transaction? (No?)
//
// Q6: If commands on this connection are
// not participating in the current transaction, will they be committed
// even if rollback the current transaction scope? (Yes?)
//
// If my thoughts are correct, all of the above is disturbing,
// because it would look like I'm executing commands
// in a transaction scope, when in fact I'm not at all,
// until I do the following...
//
// Now enlisting existing connection in current transaction
conn.EnlistTransaction( Transaction.Current );
//
// Q7: Does the above method explicitly enlist the pre-existing connection
// in the current ambient transaction, so that commands I
// execute on the connection now participate in the
// ambient transaction? (Yes?)
//
// Q8: If the existing connection was already enlisted in a transaction
// when I called the above method, what would happen? Might an error be thrown? (Probably?)
//
// Q9: If the existing connection was already enlisted in a transaction
// and I did NOT call the above method to enlist it, would any commands
// I execute on it participate in it's existing transaction rather than
// the current transaction scope. (Yes?)
}

最佳答案

自从提出这个问题以来,我已经做了一些测试,并且我自己找到了大部分(如果不是全部)答案,因为没有其他人回答。如果我错过了什么,请告诉我。

Q1: Is connection automatically enlisted in transaction?


是的,除非 enlist=false在连接字符串中指定。连接池找到一个可用的连接。可用连接是未登记在事务中或登记在同一事务中的连接。

Q2: If I open (and run commands on) a second connection now, with an identical connection string, what, if any, is the relationship of this second connection to the first?


第二个连接是一个独立的连接,参与同一个事务。我不确定这两个连接上命令的交互,因为它们针对同一个数据库运行,但我认为如果同时在两个连接上发出命令,可能会发生错误:错误如 "Transaction context in use by another session"

Q3: Will this second connection's automatic enlistment in the current transaction scope cause the transaction to be escalated to a distributed transaction?


是的,它会升级为分布式事务,因此即使使用相同的连接字符串,征用多个连接也会导致它成为分布式事务,这可以通过在 Transaction.Current.TransactionInformation.DistributedIdentifier 检查非空 GUID 来确认。 .
*更新:我在某处读到这在 SQL Server 2008 中是固定的,因此当两个连接使用相同的连接字符串时不使用 MSDTC(只要两个连接不是同时打开)。这允许您在一个事务中多次打开和关闭连接,这可以通过尽可能晚地打开连接并尽快关闭它们来更好地利用连接池。

Q4: If I start executing commands on the connection now, will it automatically become enlisted in the current transaction scope?


否。当没有事务作用域处于事件状态时打开的连接不会自动登记在新创建的事务作用域中。

Q5: If not enlisted, will commands I execute on the connection now participate in the ambient transaction?


不会。除非你在事务范围内打开一个连接,或者在范围内登记一个现有的连接,否则基本上没有 TRANSACTION。您的连接必须自动或手动登记在事务范围内,以便您的命令参与事务。

Q6: If commands on this connection are not participating in the current transaction, will they be committed even if rollback the current transaction scope?


是的,即使代码恰好在回滚的事务范围块中执行,但未参与事务的连接上的命令仍按发出的方式提交。如果连接未在当前事务范围内登记,则它不参与事务,因此提交或回滚事务对在未登记在事务范围内的连接上发出的命令没有影响...如 this guy found out .除非您了解自动登记过程,否则很难发现这一点:它仅在事件事务范围内打开连接时发生。

Q7: Does the above method explicitly enlist the pre-existing connection in the current ambient transaction, so that commands I execute on the connection now participate in the ambient transaction?


是的。可以通过调用 EnlistTransaction(Transaction.Current) 在当前事务范围内显式登记现有连接。 .您还可以通过使用 DependentTransaction 在事务中的单独线程上登记一个连接,但像以前一样,我不确定同一个事务中针对同一个数据库的两个连接如何交互......并且可能会发生错误,并且当然,第二个登记的连接会导致事务升级为分布式事务。

Q8: If the existing connection was already enlisted in a transaction when I called the above method, what would happen? Might an error be thrown?


可能会抛出错误。如 TransactionScopeOption.Required被使用,并且连接已经登记在事务范围事务中,则没有错误;实际上,没有为作用域创建新事务,事务计数 ( @@trancount ) 没有增加。但是,如果您使用 TransactionScopeOption.RequiresNew ,然后在尝试在新事务范围事务中登记连接时收到有用的错误消息:“连接当前已登记事务。完成当前事务并重试。”是的,如果您完成了连接被登记的事务,您可以安全地在新事务中登记该连接。
*更新:如果您之前拨打过 BeginTransaction在连接上,当您尝试在新的事务范围事务中登记时会抛出一个略有不同的错误:“无法登记在事务中,因为本地事务正在进行连接。完成本地事务并重试。”另一方面,您可以安全地拨打 BeginTransactionSqlConnection而它在事务范围事务中登记,这实际上会增加 @@trancount一,不像使用嵌套事务范围的Required选项,这不会导致它增加。有趣的是,如果您继续使用 Required 创建另一个嵌套事务范围。选项,你不会得到错误,因为已经有一个事件的事务范围事务没有任何变化(记住当事务范围事务已经事件并且使用 @@trancount 选项时 Required 不会增加)。

Q9: If the existing connection was already enlisted in a transaction and I did NOT call the above method to enlist it, would any commands I execute on it participate in its existing transaction rather than the current transaction scope?


是的。无论 C# 代码中的事件事务范围是什么,命令都会参与连接所登记的任何事务。

关于c# - 在什么情况下 SqlConnection 会自动加入环境 TransactionScope 事务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2884863/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com