Обработка сбоев фиксации транзакций
Примечание.
ТОЛЬКО EF6.1 — функции, API и т. д., рассмотренные на этой странице, были представлены в Entity Framework 6.1. При использовании более ранней версии могут быть неприменимы некоторые или все сведения.
В рамках версии 6.1 мы представляем новую функцию устойчивости подключения для EF: возможность обнаруживать и восстанавливаться автоматически, когда временные сбои подключения влияют на подтверждение фиксаций транзакций. Полные сведения о сценарии лучше всего описаны в записи блога База данных SQL Подключение ivity и idempotency Issue. В итоге сценарий заключается в том, что при возникновении исключения во время фиксации транзакции существует две возможные причины:
- Сбой фиксации транзакции на сервере
- Фиксация транзакции выполнена успешно на сервере, но проблема с подключением не позволила ему достичь уведомления об успешном выполнении.
Когда первая ситуация происходит с приложением или пользователь может повторить операцию, но при второй ситуации следует избежать повторных попыток, и приложение может восстановиться автоматически. Проблема заключается в том, что без возможности обнаруживать фактическую причину, по которой было сообщено исключение во время фиксации, приложение не может выбрать правильный курс действия. Новая функция в EF 6.1 позволяет EF дважды проверка с базой данных, если транзакция прошла успешно, и провести правильный курс действий прозрачно.
Использование компонента
Чтобы включить необходимую функцию, включите вызов SetTransactionHandler в конструктор dbConfiguration. Если вы не знакомы с DbConfiguration, см . раздел "Конфигурация на основе кода". Эту функцию можно использовать в сочетании с автоматическими повторными попытками, представленными в EF6, что помогает в ситуации, в которой транзакция фактически не смогла зафиксировать на сервере из-за временных сбоев:
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.SqlServer;
public class MyConfiguration : DbConfiguration
{
public MyConfiguration()
{
SetTransactionHandler(SqlProviderServices.ProviderInvariantName, () => new CommitFailureHandler());
SetExecutionStrategy(SqlProviderServices.ProviderInvariantName, () => new SqlAzureExecutionStrategy());
}
}
Отслеживание транзакций
Если эта функция включена, EF автоматически добавит новую таблицу в базу данных с именем __Transactions. Новая строка вставляется в эту таблицу каждый раз, когда транзакция создается EF, и эта строка проверка для существования, если во время фиксации возникает сбой транзакции.
Хотя EF будет делать лучшие усилия, чтобы обрезать строки из таблицы, если они больше не нужны, таблица может расти, если приложение завершается преждевременно, и по этой причине может потребоваться очистить таблицу вручную в некоторых случаях.
Обработка сбоев фиксации с предыдущими версиями
До EF 6.1 не было механизма обработки сбоев фиксации в продукте EF. Существует несколько способов решения этой ситуации, которые можно применить к предыдущим версиям EF6:
Вариант 1. Ничего не делать
Вероятность сбоя подключения во время фиксации транзакций низка, поэтому оно может быть приемлемым для приложения, чтобы просто завершиться ошибкой, если это условие на самом деле происходит.
Вариант 2. Использование базы данных для сброса состояния
- Dis карта current DbContext
- Создание dbContext и восстановление состояния приложения из базы данных
- Сообщите пользователю, что последняя операция не была выполнена успешно
Вариант 3. Отслеживание транзакции вручную
- Добавьте не отслеживаемую таблицу в базу данных, используемую для отслеживания состояния транзакций.
- Вставьте строку в таблицу в начале каждой транзакции.
- Если подключение завершается ошибкой во время фиксации, проверка наличие соответствующей строки в базе данных.
- Если строка присутствует, продолжайте обычно, так как транзакция была успешно зафиксирована
- Если строка отсутствует, используйте стратегию выполнения, чтобы повторить текущую операцию.
- Если фиксация выполнена успешно, удалите соответствующую строку, чтобы избежать роста таблицы.
В этой записи блога содержится пример кода для выполнения этого в SQL Azure.