我曾经使用 TransactionOptions.Timeout 来设置事务超时,但已决定使用配置方法来简化维护:
<system.transactions>
<defaultSettings timeout="00:01:00" />
</system.transactions>
当然,在把它放入之后,我想测试它是否正常工作,所以将超时时间减少到5秒,然后运行一个持续时间超过这个的测试 - 但事务似乎没有中止!如果我调整测试以将TransactionOptions.Timeout设置为5秒,则测试按预期工作
调查后我认为问题似乎与TransactionOptions.Timeout有关,即使我不再使用它。
我仍然需要使用TransactionOptions,所以我可以设置IsolationLevel,但我不再设置Timeout值,如果我在创建它后查看此对象,则超时值为00:00:00,相当于无穷大。这是否意味着我的配置文件中设置的值被忽略了?
总结:
答案 0 :(得分:46)
您可以混合使用system.transaction配置设置和使用TransactionOption
类,但有些事情需要注意。
如果您使用
TransactionOption
和 指定Timeout
值,即该值 将被用于 System.Transactions的/ defaultTimeout 值。
以上是我认为问题的症结所在。您正在使用TransactionOption
指定隔离级别,并且作为副作用,您将获得无限超时值,因为无限是{的默认超时值{1}}如果未指定。虽然,我不太清楚为什么会这样......默认为默认的事务超时是有意义的。
您可以实现自己的TransactionOptions帮助程序类,其中包括从app.config读取的默认值(如果找到)或默认为可以使用的TransactionOption类的合理值。
在任何情况下,您仍然可以使用 system.transaction / machineSettings / maxTimeout 值来限制此值。这是一个管理设置,只能通过machine.config进行配置。如果你从app / web.config尝试它,你会得到一个ConfigurationException。
TransactionOption
设置 maxTimeout 后,无论您指定的超时值如何,最大值都将限制为maxTimeout值。默认的maxTimeout是00:10:00或10分钟,因此您实际上不会在事务上有无限超时。
您还可以在事务中使用的数据库连接上设置事务IsolationLevel 显式。像这样的东西?
<system.transactions>
<machineSettings maxTimeout="00:00:30" />
</system.transactions>
在测试中,您可能需要确保重建以便重新生成app.config。在我的测试中,似乎我需要终止* .vshost.exe进程,以便它获取system.transaction配置设置更改 - 尽管我觉得这可能是一个侥幸。只是fyi ..
答案 1 :(得分:46)
您可以使用TransactionManager.DefaultTimeout
从配置中获取(验证的)默认超时。
TransactionOptions
是一个封装超时和隔离级别的结构。使用默认构造函数初始化struct时,它总是将struct成员初始化为其默认值:
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
};
答案 2 :(得分:11)
Per Reflector,使用TransactionScope
的构造函数设置事务超时的基本规则如下:
DefaultTimeOut 由满足以下条件的第一条规则决定:
TimeSpan
参数,则DefaultTimeout是该参数TransactionOption
参数,则DefaultTimeout为transactionOption.TimeOut
TransactionScopeOption
参数,则DefaultTimeout为scopeOption.TimeOut
除非在machine.config中指定了其他值,否则 MaxTimeOut 为10分钟。
事务的有效超时小于MaxTimeOut和DefaultTimeOut,大于零。如果MaxTimeOut和DefaultTimeOut都为零,则有效超时是由long.MaxValue
(无穷大)表示的刻度数。
如果TransactionScope
实例未创建新事务,或者因为事务被传递到其构造函数中,或者因为事务范围选项不需要它(例如,当存在环境事务并且TransactionScopeOption是必需),但仍在构造函数中传递timeOut
参数,启动计时器。超时期限过去后,将调用基础事务的TimeOut()
方法。在这种情况下不使用DefaultTimeOut和MaxTimeOut属性。
如果transactionScopeOption == TransactionScopeOption.Supress
,则忽略超时并且无效。
如果覆盖了machine.config中的相关部分,也可以在app / web配置文件中定义MaxTimeOut(请注意allowDefintion和allowExeDefinition属性的值):
<sectionGroup name="system.transactions" type="System.Transactions.Configuration.TransactionsSectionGroup, System.Transactions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, Custom=null">
<section name="defaultSettings" type="System.Transactions.Configuration.DefaultSettingsSection, System.Transactions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, Custom=null"/>
<section name="machineSettings" type="System.Transactions.Configuration.MachineSettingsSection, System.Transactions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, Custom=null" allowDefinition="MachineToApplication" allowExeDefinition="MachineToApplication"/>
</sectionGroup>
为了快速参考,这里是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);
答案 3 :(得分:6)
使用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;
答案 4 :(得分:2)
void Main()
{
var maximumTimeout = TransactionManager.MaximumTimeout;//This step is necessary to init _maximumTimeout value,
FieldInfo fieldInfo = typeof(TransactionManager).GetFields(BindingFlags.NonPublic | BindingFlags.Static).Single(item => item.Name == "_maximumTimeout");
var customMaximumTimeout = TimeSpan.FromHours(1);
fieldInfo.SetValue(null, customMaximumTimeout);
maximumTimeout = TransactionManager.MaximumTimeout;
Console.WriteLine(maximumTimeout);//01:00:00
// use TransactionScope
}
答案 5 :(得分:1)
把我当前的想法放下来: