.net 默认事务超时

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1348191/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 13:13:51  来源:igfitidea点击:

Default Transaction Timeout

.netconfigurationtransactionstimeout

提问by MattH

I used to set Transaction timeouts by using TransactionOptions.Timeout, but have decided for ease of maintenance to use the config approach:

我曾经使用TransactionOptions.Timeout设置事务超时,但为了便于维护,我决定使用配置方法:

 <system.transactions>
    <defaultSettings timeout="00:01:00" />
  </system.transactions>

Of course, after putting this in, I wanted to test it was working, so reduced the timeout to 5 seconds, then ran a test that lasted longer than this - but the transaction does not appear to abort! If I adjust the test to set TransactionOptions.Timeout to 5 seconds, the test works as expected

当然,在把它放进去之后,我想测试它是否正常工作,所以将超时减少到 5 秒,然后运行一个持续时间比这更长的测试 - 但交易似乎没有中止!如果我调整测试以将 TransactionOptions.Timeout 设置为 5 秒,则测试按预期工作

After Investigating I think the problem appears to relate to TransactionOptions.Timeout, even though I'm no longer using it.

调查后我认为问题似乎与 TransactionOptions.Timeout 有关,即使我不再使用它。

I still need to use TransactionOptions so I can set IsolationLevel, but I no longer set the Timeout value, if I look at this object after I create it, the timeout value is 00:00:00, which equates to infinity. Does this mean my value set in the config file is being ignored?

我仍然需要使用TransactionOptions来设置IsolationLevel,但是我不再设置Timeout值,如果我在创建它之后查看这个对象,超时值是00:00:00,相当于无穷大。这是否意味着我在配置文件中设置的值被忽略了?

To summarise:

总结一下:

  • Is it impossible to mix the config setting, and use of TransactionOptions
  • If not, is there any way to extract the config setting at runtime, and use this to set the Timeout property
  • [Edit] ORSet the default isolation-level without using TransactionOptions
  • 混合配置设置和使用 TransactionOptions 是不可能的
  • 如果没有,有没有办法在运行时提取配置设置,并使用它来设置超时属性
  • [编辑] 或在不使用 TransactionOptions 的情况下设置默认隔离级别

回答by Ronald

You can get the (validated) default timeout from the configuration using TransactionManager.DefaultTimeout.

您可以使用TransactionManager.DefaultTimeout.

TransactionOptionsis a struct that encapsulates timeout and isolation level. When initializing a structusing the default constructor, it will always initialize the struct members to their default values:

TransactionOptions是一个封装了超时和隔离级别的结构体。使用默认构造函数初始化结构时,它总是将结构成员初始化为其默认值:

TransactionOptions transactionOptions = new TransactionOptions();
transactionOptions.Timeout == default(TimeSpan); // TimeSpan.Zero
transactionOptions.IsolationLevel == default(IsolationLevel); // IsolationLevel.Serializable

If you want to specify an IsolationLeveland use the default timeout:

如果要指定一个IsolationLevel并使用默认超时:

new TransactionOptions()
{
    IsolationLevel = IsolationLevel.Serializable, // Use whatever level you require
    Timeout = TransactionManager.DefaultTimeout
};

回答by Zach Bonham

You can mix system.transaction configuration settings and the use of the TransactionOptionclass, but there are some things you need to be aware of.

您可以混合使用 system.transaction 配置设置和TransactionOption类的使用,但有一些事情您需要注意。

If you use the TransactionOptionand specify a Timeoutvalue, that value will be used over the system.transactions/defaultTimeout value.

如果您使用TransactionOption并指定一个Timeout值,则该值将用于 system.transactions/defaultTimeout 值。

The above is the crux of the problem in your case I think. You are using the TransactionOptionto specify the isolationlevel, and as a side effect you are getting an infiniteTimeout value because infinite is the default Timeout value for TransactionOptionif its not specified. Though, I'm not quite sure why that is...it would make sense to default to the default Transaction Timeout.

以上是我认为在你的情况下问题的症结所在。您正在使用TransactionOption来指定隔离级别,并且作为副作用,您将获得无限超时值,因为TransactionOption如果未指定,则无限是默认超时值。不过,我不太确定为什么会这样......默认为默认的事务超时是有意义的。

You can implement your own TransactionOptions helper class that includes defaults that are read from app.config (if found) or default to reasonable values for a TransactionOption class that can be used.

您可以实现自己的 TransactionOptions 帮助程序类,其中包括从 app.config(如果找到)读取的默认值或默认为可以使用的 TransactionOption 类的合理值。

In any case, you can still limit this by using the system.transaction/machineSettings/maxTimeoutvalue. This is an administrative setting and can only be configured through the machine.config. You'll get a ConfigurationException if you try it from app/web.config.

在任何情况下,您仍然可以通过使用system.transaction/machineSettings/maxTimeout值来限制它。这是一项管理设置,只能通过 machine.config 进行配置。如果您从 app/web.config 尝试,您将收到 ConfigurationException。

<system.transactions>
    <machineSettings maxTimeout="00:00:30" />
</system.transactions>

With the maxTimeoutset, no matter what timeout value you specify, the maximum value will be limited to the maxTimeout value. The default maxTimeout is 00:10:00, or 10 minutes, so you wouldn't actually ever have an infinite timeout on a transaction.

随着maxTimeout集,不管你指定什么超时值,最大值将被限制到maxTimeout值。默认的 maxTimeout 是 00:10:00 或 10 分钟,因此您实际上不会在事务上无限超时。

You can also set the transaction IsolationLevel explicitlyon the database connection you are using within the transaction. Something like this?

您还可以在事务中使用的数据库连接上显式设置事务 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();

            }

In your testing, you may need to make sure you rebuild so that the app.config is regenerated . In my testing, it appeared that I needed to terminate the *.vshost.exe process in order for it to pick up the system.transaction configuration setting change - though I feel that may have been a fluke. Just fyi..

在您的测试中,您可能需要确保重建以便重新生成 app.config 。在我的测试中,似乎我需要终止 *.vshost.exe 进程才能使其接受 system.transaction 配置设置更改 - 尽管我觉得这可能是侥幸。仅供参考..

回答by Raghu Dodda

Per Reflector, the basic rules for setting a transaction time out with the constructors of TransactionScopeare as follows:

对于每个反射器,使用 的构造函数设置事务超时的基本规则TransactionScope如下:

The DefaultTimeOutis determined by the first rule from below that is satisfied:

DefaultTimeOut由第一规则确定从下满足:

  • if the constructor has a TimeSpanparameter, the DefaultTimeout is the that parameter
  • if the constructor has a TransactionOptionparameter, the DefaultTimeout is transactionOption.TimeOut
  • if the constructor has a TransactionScopeOptionparameter, the DefaultTimeout is scopeOption.TimeOut
  • if the constructor does not have timeout parameter, the DefaultTimeout is the value specified in the app or web config file.
  • otherwise, DefaultTimeOut is 1 minute.
  • 如果构造函数有TimeSpan参数,则 DefaultTimeout 是该参数
  • 如果构造函数有TransactionOption参数,则 DefaultTimeout 是transactionOption.TimeOut
  • 如果构造函数有TransactionScopeOption参数,则 DefaultTimeout 是scopeOption.TimeOut
  • 如果构造函数没有超时参数,则 DefaultTimeout 是应用程序或 Web 配置文件中指定的值。
  • 否则,DefaultTimeOut 为 1 分钟。

The MaxTimeOutis 10 minutes unless another value is specified in the machine.config.

所述MaxTimeOut为10分钟,除非在machine.config指定另一值。

The effective timeoutfor the transaction is smaller of the MaxTimeOut and DefaultTimeOut that is greater than zero. If both MaxTimeOut and DefaultTimeOut are zero, the effective timeout is the number of ticks represented by long.MaxValue(the infinity).

事务的有效超时小于 MaxTimeOut 和 DefaultTimeOut 中大于零的值。如果 MaxTimeOut 和 DefaultTimeOut 都为零,则有效超时是由long.MaxValue(无穷大)表示的滴答数。

If the TransactionScopeinstance does not create a new transaction either because a transaction is passed into its constructor, or because the transaction scope option does not require it (e.g., when an ambient transaction is present and the TransactionScopeOption is Required), but a timeOutparameter is still passed in the constructor, a timer is started. When the timeout period elapses, the underlying transaction's TimeOut()method is called. The DefaultTimeOut and MaxTimeOut properties are not used in this case.

如果TransactionScope实例没有创建新的事务,要么是因为事务被传递到它的构造函数,要么是因为事务范围选项不需要它(例如,当存在环境事务并且需要 TransactionScopeOption 时),但timeOut参数仍然是传入构造函数,启动计时器。当超时时间过去后,底层事务的TimeOut()方法被调用。在这种情况下不使用 DefaultTimeOut 和 MaxTimeOut 属性。

If the transactionScopeOption == TransactionScopeOption.Supress, the timeout is ignored and has no effect.

如果transactionScopeOption == TransactionScopeOption.Supress,超时将被忽略且无效。

It is also possible to define the MaxTimeOut in the app/web config file, if the relevant section in the machine.config is overridden (note the values of the allowDefintion and allowExeDefinition attributes):

如果 machine.config 中的相关部分被覆盖(注意 allowDefintion 和 allowExeDefinition 属性的值),也可以在 app/web 配置文件中定义 MaxTimeOut:

<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>

For quick reference, here are the TransactionScope constructors:

为了快速参考,以下是 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);

回答by Mike Two

The config file setting is ignored when TransactionOptions are used. Creating a TransactionScope will, in most cases, create an instance of CommittableTransaction. The no arg constructor of CommittableTransaction will use the config file setting as its default timeout. TransactionScope constructors that take a TransactionOptions or TimeSpan will call one of the overloads of the CommittableTransaction class and not the no arg version. So if you want to use that value you have to grab it from the config file yourself.

使用 TransactionOptions 时将忽略配置文件设置。在大多数情况下,创建 TransactionScope 将创建 CommittableTransaction 的实例。CommittableTransaction 的无参数构造函数将使用配置文件设置作为其默认超时。采用 TransactionOptions 或 TimeSpan 的 TransactionScope 构造函数将调用 CommittableTransaction 类的重载之一,而不是无参数版本。因此,如果您想使用该值,您必须自己从配置文件中获取它。

When I ran into this I put the following code in a little TransactionOptionsFactory class.

当我遇到这个时,我将以下代码放在一个小的 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;

回答by Franz

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
}

回答by MattH

To put my current thoughts down:

把我现在的想法写下来:

  • It is impossible to mix the config setting, and use of TransactionOptions
  • The only way to extract the config setting at runtime is to read the app.config as an XML file
  • The default isolation-level can only be done via transaction options, or at the service-level in WCF using attributes
  • 混合配置设置和使用 TransactionOptions 是不可能的
  • 在运行时提取配置设置的唯一方法是将 app.config 作为 XML 文件读取
  • 默认隔离级别只能通过事务选项完成,或者在 WCF 中使用属性在服务级别完成