Шрифт:
Интервал:
Закладка:
static void SampleSaveChanges()
{
// Фабрика не предназначена для такого использования,
// но это демонстрационный код
var context = new ApplicationDbContextFactory().CreateDbContext(null);
// Внести какие-нибудь изменения.
context.<b>SaveChanges()</b>;
}
В оставшемся материале главы (и книги) вы обнаружите много примеров сохранения изменений.
Поддержка транзакций и точек сохранения
Исполняющая среда EF Core помещает каждый вызов SaveChanges()/SaveChangesAsync() внутрь неявной транзакции, использующей уровень изоляции базы данных. Чтобы добиться большей степени контроля, можете включить экземпляр производного класса DbContext в явную транзакцию. Для выполнения явной транзакции создайте транзакцию с применением свойства Database класса, производного от DbContext. Управляйте своими операциями обычным образом и затем предпримите фиксацию или откат транзакции. Ниже приведен фрагмент кода, где все демонстрируется:
using var trans = context.Database.BeginTransaction();
try
{
// Создать, изменить, удалить запись.
context.SaveChanges();
trans.Commit();
}
catch (Exception ex)
{
trans.Rollback();
}
В версии EF Core 5 были введены точки сохранения для транзакций EF Core. Когда вызывается метод SaveChanges()/SaveChangesAsync(), а транзакция уже выполняется, исполняющая среда EF Core создает в этой транзакции точку сохранения. Если вызов терпит неудачу, то откат транзакции происходит в точку сохранения, а не в начало транзакции. Точками сохранения можно также управлять в коде, вызывая методы CreateSavePoint() и RollbackToSavepoint() для транзакции:
using var trans = context.Database.BeginTransaction();
try
{
// Создать, изменить, удалить запись.
trans.CreateSavepoint("check point 1");
context.SaveChanges();
trans.Commit();
}
catch (Exception ex)
{
trans. RollbackToSavepoint("check point 1");
}
Транзакции и стратегии выполнения
В случае активной стратегии выполнения (как при использовании EnableRetryOnFailure()) перед созданием явной транзакции вы должны получить ссылку на текущую стратегию выполнения, которая применяется EF Core. Затем вызовите на этой стратегии метод Execute(), чтобы создать явную транзакцию:
(window.adrunTag = window.adrunTag || []).push({v: 1, el: 'adrun-4-390', c: 4, b: 390})var strategy = context.Database.CreateExecutionStrategy();
strategy.Execute(() =>
{
using var trans = context.Database.BeginTransaction();
try
{
actionToExecute();
trans.Commit();
}
catch (Exception ex)
{
trans.Rollback();
}
});
События SavingChanges/SavedChanges
В версии EF Core 5 появились три новых события, которые инициируются методами SaveChanges()/SaveChangesAsync(). Событие SavingChanges запускается при вызове SaveChanges(), но перед выполнением операторов SQL в хранилище данных, а событие SavedChanges — после завершения работы метода SaveChanges(). В следующем (простейшем) коде демонстрируются события и их обработчики в действии:
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
SavingChanges += (sender, args) =>
{
Console.WriteLine($"Saving changes for {((DbContext)sender).Database.
GetConnectionString()}");
};
SavedChanges += (sender, args) =>
{
Console.WriteLine($"Saved {args.EntitiesSavedCount} entities");
};
SaveChangesFailed += (sender, args) =>
{
Console.WriteLine($"An exception occurred! {args.Exception.Message}
entities");
};
}
Класс DbSet<T>
Для каждой сущности в своей объектной модели вы добавляете свойство типа DbSet<T>. Класс DbSet<T> представляет собой специализированную коллекцию, используемую для взаимодействия с поставщиком баз данных с целью получения, добавления, обновления и удаления записей в базе данных. Каждая коллекция DbSet<T> предлагает несколько основных служб для взаимодействия с базой данных. Любые запросы LINQ, запускаемые в отношении класса DbSet<T>, транслируются поставщиком базы данных в запросы к базе данных. В табл. 22.2 описан ряд основных членов класса DbSet<T>.
- Понимание SQL - Мартин Грубер - Базы данных