我曾经使用TransactionOptions.Timeout设置事务超时,但已决定使用配置方法来简化维护:
当然,在把它放入之后,我想测试它是否正常工作,所以将超时时间减少到5秒,然后运行一个持续时间超过这个的测试 - 但事务似乎没有中止!如果我调整测试以将TransactionOptions.Timeout设置为5秒,则测试按预期工作
调查后我认为问题似乎与TransactionOptions.Timeout有关,即使我不再使用它.
我仍然需要使用TransactionOptions,所以我可以设置IsolationLevel,但我不再设置Timeout值,如果我在创建它之后查看此对象,则超时值为00:00:00,相当于无穷大.这是否意味着我的配置文件中设置的值被忽略了?
总结一下:
是否无法混合配置设置和TransactionOptions的使用
如果没有,是否有任何方法可以在运行时提取配置设置,并使用它来设置Timeout属性
[编辑]或设置默认隔离级别而不使用TransactionOptions
Ronald.. 47
您可以使用配置获取(验证的)默认超时TransactionManager.DefaultTimeout
.
TransactionOptions
是一个封装超时和隔离级别的结构.使用默认构造函数初始化结构时,它总是将结构成员初始化为其默认值:
TransactionOptions transactionOptions = new TransactionOptions(); transactionOptions.Timeout == default(TimeSpan); // TimeSpan.Zero transactionOptions.IsolationLevel == default(IsolationLevel); // IsolationLevel.Serializable
如果要指定IsolationLevel
并使用默认超时:
new TransactionOptions() { IsolationLevel = IsolationLevel.Serializable, // Use whatever level you require Timeout = TransactionManager.DefaultTimeout };
Zach Bonham.. 46
您可以混合使用system.transaction配置设置和TransactionOption
类的使用,但有些事情需要注意.
如果使用
TransactionOption
并指定一个Timeout
值,则该值将用于system.transactions/defaultTimeout值.
以上是我认为问题的症结所在.您正在使用TransactionOption
指定隔离级别,并且作为副作用,您将获得无限超时值,因为TransactionOption
如果未指定,则无限是默认的超时值.虽然,我不太清楚为什么会这样......默认为默认的Transaction Timeout是有意义的.
您可以实现自己的TransactionOptions帮助程序类,其中包括从app.config(如果找到)读取的默认值,或者默认为可以使用的TransactionOption类的合理值.
在任何情况下,您仍然可以使用system.transaction/machineSettings/maxTimeout值来限制此值.这是一个管理设置,只能通过machine.config进行配置.如果您从app/web.config尝试它,您将获得ConfigurationException.
随着maxTimeout集,不管你指定什么超时值,最大值将被限制到maxTimeout值.默认的maxTimeout是00:10:00或10分钟,因此您实际上不会在事务上有无限超时.
您还可以在事务中使用的数据库连接上显式设置事务IsolationLevel .像这样的东西?
var connectionString = "Server=.;Database=master;Trusted_Connection=True;"; using (var scope = new TransactionScope(TransactionScopeOption.Required)) { using (var conn = new SqlConnection(connectionString)) { conn.Open(); var sqlTransaction = conn.BeginTransaction(System.Data.IsolationLevel.Serializable); // do database work // sqlTransaction.Commit(); } // do other work.. // scope.Complete(); }
在测试中,您可能需要确保重建以便重新生成app.config.在我的测试中,似乎我需要终止*.vshost.exe进程,以便它获取system.transaction配置设置更改 - 尽管我觉得这可能是一个侥幸.只是fyi ..
您可以使用配置获取(验证的)默认超时TransactionManager.DefaultTimeout
.
TransactionOptions
是一个封装超时和隔离级别的结构.使用默认构造函数初始化结构时,它总是将结构成员初始化为其默认值:
TransactionOptions transactionOptions = new TransactionOptions(); transactionOptions.Timeout == default(TimeSpan); // TimeSpan.Zero transactionOptions.IsolationLevel == default(IsolationLevel); // IsolationLevel.Serializable
如果要指定IsolationLevel
并使用默认超时:
new TransactionOptions() { IsolationLevel = IsolationLevel.Serializable, // Use whatever level you require Timeout = TransactionManager.DefaultTimeout };
您可以混合使用system.transaction配置设置和TransactionOption
类的使用,但有些事情需要注意.
如果使用
TransactionOption
并指定一个Timeout
值,则该值将用于system.transactions/defaultTimeout值.
以上是我认为问题的症结所在.您正在使用TransactionOption
指定隔离级别,并且作为副作用,您将获得无限超时值,因为TransactionOption
如果未指定,则无限是默认的超时值.虽然,我不太清楚为什么会这样......默认为默认的Transaction Timeout是有意义的.
您可以实现自己的TransactionOptions帮助程序类,其中包括从app.config(如果找到)读取的默认值,或者默认为可以使用的TransactionOption类的合理值.
在任何情况下,您仍然可以使用system.transaction/machineSettings/maxTimeout值来限制此值.这是一个管理设置,只能通过machine.config进行配置.如果您从app/web.config尝试它,您将获得ConfigurationException.
随着maxTimeout集,不管你指定什么超时值,最大值将被限制到maxTimeout值.默认的maxTimeout是00:10:00或10分钟,因此您实际上不会在事务上有无限超时.
您还可以在事务中使用的数据库连接上显式设置事务IsolationLevel .像这样的东西?
var connectionString = "Server=.;Database=master;Trusted_Connection=True;"; using (var scope = new TransactionScope(TransactionScopeOption.Required)) { using (var conn = new SqlConnection(connectionString)) { conn.Open(); var sqlTransaction = conn.BeginTransaction(System.Data.IsolationLevel.Serializable); // do database work // sqlTransaction.Commit(); } // do other work.. // scope.Complete(); }
在测试中,您可能需要确保重建以便重新生成app.config.在我的测试中,似乎我需要终止*.vshost.exe进程,以便它获取system.transaction配置设置更改 - 尽管我觉得这可能是一个侥幸.只是fyi ..
Per Reflector,使用构造函数设置事务超时的基本规则TransactionScope
如下:
该DefaultTimeOut由第一规则确定从下满足:
如果构造函数有TimeSpan
参数,则DefaultTimeout是该参数
如果构造函数有TransactionOption
参数,则DefaultTimeout为transactionOption.TimeOut
如果构造函数有TransactionScopeOption
参数,则DefaultTimeout为scopeOption.TimeOut
如果构造函数没有timeout参数,则DefaultTimeout是应用程序或Web配置文件中指定的值.
否则,DefaultTimeOut为1分钟.
所述MaxTimeOut为10分钟,除非在machine.config指定另一值.
事务的有效超时小于MaxTimeOut和DefaultTimeOut大于零.如果MaxTimeOut和DefaultTimeOut都为零,则有效超时是由long.MaxValue
(无穷大)表示的刻度数.
如果TransactionScope
实例未创建新事务,或者因为事务被传递到其构造函数中,或者因为事务范围选项不需要它(例如,当存在环境事务并且TransactionScopeOption是必需的时候),但timeOut
参数仍然是在构造函数中传递,启动计时器.超时期限过去后,将TimeOut()
调用基础事务的方法.在这种情况下,不使用DefaultTimeOut和MaxTimeOut属性.
如果是transactionScopeOption == TransactionScopeOption.Supress
,则忽略超时并且无效.
也可以定义MaxTimeOut在应用程序/ Web配置文件,如果在machine.config相关的部分被覆盖(注意allowDefintion的价值观和allowExeDefinition属性):
为了快速参考,这里是TransactionScope构造函数:
public TransactionScope(Transaction transactionToUse, TimeSpan scopeTimeout, EnterpriseServicesInteropOption interopOption); public TransactionScope(TransactionScopeOption scopeOption, TransactionOptions transactionOptions, EnterpriseServicesInteropOption interopOption); public TransactionScope(TransactionScopeOption scopeOption, TransactionOptions transactionOptions); public TransactionScope(TransactionScopeOption scopeOption, TimeSpan scopeTimeout); public TransactionScope(Transaction transactionToUse, TimeSpan scopeTimeout); public TransactionScope(TransactionScopeOption scopeOption);
使用TransactionOptions时,将忽略配置文件设置.在大多数情况下,创建TransactionScope将创建CommittableTransaction的实例.CommittableTransaction的no arg构造函数将使用配置文件设置作为其默认超时.采用TransactionOptions或TimeSpan的TransactionScope构造函数将调用CommittableTransaction类的重载之一而不是no arg版本.因此,如果您想使用该值,您必须自己从配置文件中获取它.
当我遇到这个时,我将以下代码放在一个TransactionOptionsFactory类中.
Configuration configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); ConfigurationSectionGroup sectionGroup = configuration.GetSectionGroup("system.transactions"); DefaultSettingsSection defaultSettings = (DefaultSettingsSection) sectionGroup.Sections["defaultSettings"]; TransactionOptions options = new TransactionOptions(); options.Timeout = defaultSettings.Timeout; options.IsolationLevel = IsolationLevel.ReadCommitted;