默认事务超时

发布于 2024-08-02 18:52:10 字数 712 浏览 1 评论 0原文

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

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

当然,放入此后,我想测试它是否正常工作,因此减少了将超时设置为 5 秒,然后运行比这更长的测试 - 但事务似乎并未中止!如果我调整测试以将 TransactionOptions.Timeout 设置为 5 秒,则测试将按预期工作。

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

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

总结一下:

  • 是否不可能混合配置 设置和使用 TransactionOptions
  • 如果没有,有吗 任何提取配置设置的方法 在运行时,并使用它来设置 超时属性
  • [编辑]或设置默认隔离级别而不使用TransactionOptions

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

 <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

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

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?

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] OR Set the default isolation-level without using TransactionOptions

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

短暂陪伴 2024-08-09 18:52:10

您可以使用 从配置中获取(经过验证的)默认超时TransactionManager.DefaultTimeout

TransactionOptions 是一个结构体封装超时和隔离级别。使用默认构造函数初始化 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
};

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

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

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

If you want to specify an IsolationLevel and use the default timeout:

new TransactionOptions()
{
    IsolationLevel = IsolationLevel.Serializable, // Use whatever level you require
    Timeout = TransactionManager.DefaultTimeout
};
最冷一天 2024-08-09 18:52:10

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

如果您使用TransactionOption并且
指定一个Timeout值,该值
将用于超过
系统交易/defaultTimeout
值。

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

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

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

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

设置了 ma​​xTimeout 后,无论您指定什么超时值,最大值都将限制为 maxTimeout 值。默认 maxTimeout 为 00:10:00,即 10 分钟,因此事务实际上不会有无限超时。

您还可以在事务中使用的数据库连接上显式设置事务隔离级别。像这样的东西吗?

   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 配置设置更改 - 尽管我觉得这可能是侥幸。仅供参考..

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

If you use the TransactionOption and
specify a Timeout value, that value
will be used over the
system.transactions/defaultTimeout
value.

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

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.

In any case, you can still limit this by using the system.transaction/machineSettings/maxTimeout value. 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.transactions>
    <machineSettings maxTimeout="00:00:30" />
</system.transactions>

With the maxTimeout set, 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.

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

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

情场扛把子 2024-08-09 18:52:10

根据 Reflector,使用 TransactionScope 的构造函数设置事务超时的基本规则如下:

DefaultTimeOut 由下面满足的第一个规则确定:

  • 如果构造函数具有 TimeSpan 参数,如果构造函数具有 TransactionOption 参数,则 DefaultTimeout 是该参数,
  • DefaultTimeout 是 transactionOption.TimeOut
  • 如果构造函数具有 TransactionOption 参数,则 构造函数有一个 TransactionScopeOption 参数,DefaultTimeout 是 scopeOption.TimeOut
  • 如果构造函数没有超时参数,则 DefaultTimeout 是应用程序或 Web 配置文件中指定的值。
  • 否则,DefaultTimeOut 为 1 分钟。

除非在 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);

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

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

  • if the constructor has a TimeSpan parameter, the DefaultTimeout is the that parameter
  • if the constructor has a TransactionOption parameter, the DefaultTimeout is transactionOption.TimeOut
  • if the constructor has a TransactionScopeOption parameter, 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.

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

The effective timeout for 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).

If the TransactionScope instance 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 timeOut parameter 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.

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

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

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

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);
无风消散 2024-08-09 18:52:10

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

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

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.

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


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;
抽个烟儿 2024-08-09 18:52:10
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
}
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
}
和我恋爱吧 2024-08-09 18:52:10

写下我目前的想法:

  • 不可能混合配置设置和使用 TransactionOptions
  • 在运行时提取配置设置的唯一方法是将 app.config 作为 XML 文件读取
  • 只能执行默认隔离级别通过事务选项,或在 WCF 中使用属性的服务级别

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文