3 Основных Способа Управления Транзакциями в EF Core. Окончание
Начало
3. Стратегия выполнения транзакций
В этом способе создаётся стратегия выполнения, в которой управляются транзакции. Она продолжает пытаться выполнить операции с БД указанное количество раз, если транзакция не удаётся из-за временной ошибки. Это итеративное поведение гарантирует, что незначительные проблемы не повлияют на фактические операции.
Добавим к зданиям различные помещения в зданиях:
public class Unit
{
public int Id { get; set; }
public string Number { get; set; }
// Office, Apartment, Storage, и т.п.
public UnitType Type { get; set; }
public int Floor { get; set; }
public int BuildingId { get; set; }
public Building Building { get; set; }
}
Создадим DTO:
public record UnitDto(
string Number, UnitType Type, int Floor);
public class BuildingDto
{
public string Name { get; set; }
public string Address { get; set; }
public List<UnitDto> Units { get; set; }
= new List<UnitDto>();
}
И, наконец, сценарий обработки:
public class BuildingRepo: IBuildingRepo
{
private AppDbContext _ctx;
public BuildingRepo(AppDbContext ctx)
{
_ctx = ctx;
}
public async Task<bool> CreateAsync(BuildingDto input)
{
// Создаём стратегию
var strategy = _ctx.Database
.CreateExecutionStrategy();
return await strategy.ExecuteAsync(async () =>
{
// Запускаем транзакцию
using (var trans =
await _ctx.Database.BeginTransactionAsync())
{
try
{
var bld = new Building()
{
Name = input.Name,
Address = input.Address
};
// Сохраняем Building
_ctx.Buildings.Add(bld);
await _ctx.SaveChangesAsync();
foreach (var unit in input.Units)
{
_ctx.Add(new Unit()
{
// Добавляем внешний ключ здания
BuildingId = bld.Id,
Number = unit.Number,
Type = unit.Type,
Floor = unit.Floor
});
}
await _ctx.SaveChangesAsync();
await trans.CommitAsync();
return true;
}
catch (Exception ex)
{
// Откатываем, транзакцию при ошибке
await trans.RollbackAsync();
// Выбрасываем исключение,
// чтобы стратегия его обработала
throw;
}
}
}
});
}
Весь блок работает как транзакция. При временном сбое стратегия выполнения повторяет всю операцию в ExecuteAsync.
Плюсы
- Стратегия может обрабатывать временные сбои, что повышает отзывчивость и надёжность приложения.
- Идеально подходит для сложных сценариев и взаимозависимых операций.
- Предлагает настройку транзакции вместе с устойчивостью к сбоям сети.
Минусы
- Ещё больше усложняет код. Множество блоков и областей влияют на читаемость кода.
- Транзакция на основе стратегии может снизить производительность приложения, если она неправильно настроена.
Источник: https://blog.elmah.io/3-essential-techniques-for-managing-transactions-in-ef-core/