Подтвердить что ты не робот

Таймаут транзакций по умолчанию

Я использовал для определения тайм-аутов транзакций с помощью TransactionOptions.Timeout, но решил упростить обслуживание для использования подхода config:

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

Конечно, после того, как я положил это, я захотел проверить, что он работает, поэтому сократил тайм-аут до 5 секунд, а затем прошел тест, который длился дольше, чем это, но транзакция не прерывается! Если я настрою тест, чтобы установить TransactionOptions.Timeout на 5 секунд, тест работает как ожидалось

После исследования Я думаю, что проблема, похоже, связана с TransactionOptions.Timeout, хотя я больше не использую ее.

Мне все еще нужно использовать TransactionOptions, поэтому я могу установить IsolationLevel, но я больше не устанавливаю значение Timeout, если я смотрю на этот объект после его создания, значение таймаута равно 00:00:00, что равнозначно бесконечности. Означает ли это, что мое значение, установленное в файле конфигурации, игнорируется?

Подводя итог:

  • Невозможно ли смешивать конфигурацию установления и использования TransactionOptions
  • Если нет, есть ли любой способ извлечь настройку конфигурации во время выполнения, и используйте это, чтобы установить Свойство тайм-аута
  • [Изменить] ИЛИ Установить уровень изоляции по умолчанию без использования TransactionOptions
4b9b3361

Ответ 1

Вы можете смешивать параметры конфигурации system.transaction и использование класса TransactionOption, но есть некоторые вещи, о которых вам нужно знать.

Если вы используете TransactionOption и укажите значение Timeout, это значение будет использоваться над System.Transactions/defaultTimeout значение.

Вышеупомянутая суть проблемы в вашем случае, я думаю. Вы используете TransactionOption, чтобы указать уровень изоляции, а в качестве побочного эффекта вы получаете бесконечное значение Timeout, так как бесконечность - это значение по умолчанию для таймаута для TransactionOption, если оно не указано. Хотя, я не совсем уверен, почему это... было бы разумно по умолчанию использовать Таймаут транзакций по умолчанию.

Вы можете реализовать свой собственный вспомогательный класс TransactionOptions, который включает значения по умолчанию, которые считываются из app.config(если найден) или по умолчанию для разумных значений для класса TransactionOption, который можно использовать.

В любом случае вы все равно можете ограничить это, используя значение system.transaction/machineSettings/maxTimeout. Это административный параметр, который можно настроить только через machine.config. Вы получите ConfigurationException, если вы попробуете его из приложения /web.config.

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

С помощью 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..

Ответ 2

Вы можете получить (проверенный) тайм-аут по умолчанию из конфигурации с помощью 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
};

Ответ 3

В рефлекторе основные правила для установки времени транзакции с конструкторами TransactionScope заключаются в следующем:

DefaultTimeOut определяется первым правилом снизу, которое выполняется:

  • Если конструктор имеет параметр TimeSpan, DefaultTimeout - это параметр
  • Если конструктор имеет параметр TransactionOption, значение DefaultTimeout равно transactionOption.TimeOut
  • Если конструктор имеет параметр TransactionScopeOption, значение DefaultTimeout равно scopeOption.TimeOut
  • Если конструктор не имеет параметра тайм-аута, значение DefaultTimeout является значением, указанным в файле приложения или веб-конфигурации.
  • иначе, DefaultTimeOut - 1 минута.

MaxTimeOut - 10 минут, если другое значение не указано в файле machine.config.

эффективный тайм-аут для транзакции меньше значений MaxTimeOut и DefaultTimeOut, который больше нуля. Если оба значения MaxTimeOut и DefaultTimeOut равны нулю, эффективным таймаутом является количество тиков, представленных long.MaxValue (бесконечность).

Если экземпляр TransactionScope не создает новую транзакцию либо потому, что транзакция передается в ее конструктор, либо потому, что параметр области транзакции не требует ее (например, когда присутствует внешняя транзакция и требуется TransactionScopeOption), но параметр timeOut по-прежнему передается в конструкторе, запускается таймер. Когда истекает период ожидания, вызывается метод транзакции TimeOut(). В этом случае свойства DefaultTimeOut и MaxTimeOut не используются.

Если transactionScopeOption == TransactionScopeOption.Supress, таймаут игнорируется и не имеет эффекта.

Также возможно определить MaxTimeOut в файле app/web config, если соответствующий раздел в файле machine.config переопределен (обратите внимание на значения атрибутов 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);

Ответ 4

Настройка файла конфигурации игнорируется при использовании TransactionOptions. Создание TransactionScope в большинстве случаев приведет к созданию экземпляра CommittableTransaction. Конструктор no arg CommittableTransaction будет использовать настройку файла конфигурации в качестве таймаута по умолчанию. Конструкторы TransactionScope, которые используют TransactionOptions или TimeSpan, будут вызывать одну из перегрузок класса 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;

Ответ 5

Чтобы убрать мои текущие мысли:

  • Невозможно смешать настройку конфигурации и использовать TransactionOptions
  • Единственный способ извлечь настройку конфигурации во время выполнения - прочитать файл app.config как файл XML
  • Уровень изоляции по умолчанию может выполняться только с помощью параметров транзакции или на уровне сервиса в WCF с использованием атрибутов

Ответ 6

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
}