Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Подсказка
Вы можете скачать пример событий из GitHub.
Entity Framework Core (EF Core) предоставляет события .NET для обратного вызова при возникновении определенных событий в коде EF Core. События проще перехватчиков и позволяют более гибкую регистрацию. Однако они только синхронные, и поэтому не могут выполнять асинхронные операции ввода-вывода.
События регистрируются в экземпляре DbContext. Используйте прослушиватель диагностики для получения той же информации, но для всех экземпляров DbContext, участвующих в процессе.
События, вызванные EF Core
Следующие события вызываются EF Core:
| Событие | При поднятии |
|---|---|
| DbContext.SavingChanges | В начале SaveChanges или SaveChangesAsync |
| DbContext.SavedChanges | В конце успешного SaveChanges или SaveChangesAsync |
| DbContext.SaveChangesFailed | В конце неудачного SaveChanges или SaveChangesAsync |
| ChangeTracker.Tracked | Когда сущность отслеживается контекстом |
| ChangeTracker.StateChanged | При изменении состояния отслеживаемой сущности |
Пример. Изменения состояния метки времени
Каждая сущность, отслеживаемая DbContext, имеет EntityState. Например, состояние Added указывает, что сущность будет вставлена в базу данных.
В этом примере используются события Tracked и StateChanged для обнаружения изменения состояния сущности. Затем он ставит метку на сущности, указывающую текущее время, показывающее, когда произошло это изменение. Это приводит к меткам времени, указывающим, когда сущность была вставлена, удалена и /или последнее обновление.
Типы сущностей в этом примере реализуют интерфейс, определяющий свойства метки времени:
public interface IHasTimestamps
{
DateTime? Added { get; set; }
DateTime? Deleted { get; set; }
DateTime? Modified { get; set; }
}
Затем метод dbContext приложения может задать метки времени для любой сущности, реализующей этот интерфейс:
private static void UpdateTimestamps(object sender, EntityEntryEventArgs e)
{
if (e.Entry.Entity is IHasTimestamps entityWithTimestamps)
{
switch (e.Entry.State)
{
case EntityState.Deleted:
entityWithTimestamps.Deleted = DateTime.UtcNow;
Console.WriteLine($"Stamped for delete: {e.Entry.Entity}");
break;
case EntityState.Modified:
entityWithTimestamps.Modified = DateTime.UtcNow;
Console.WriteLine($"Stamped for update: {e.Entry.Entity}");
break;
case EntityState.Added:
entityWithTimestamps.Added = DateTime.UtcNow;
Console.WriteLine($"Stamped for insert: {e.Entry.Entity}");
break;
}
}
}
Этот метод имеет подходящую сигнатуру для использования в качестве обработчика как для событий Tracked, так и StateChanged. Обработчик регистрируется для обоих событий в конструкторе DbContext. Обратите внимание, что события можно подключить к DbContext в любое время; Не требуется, чтобы это произошло в конструкторе контекста.
public BlogsContext()
{
ChangeTracker.StateChanged += UpdateTimestamps;
ChangeTracker.Tracked += UpdateTimestamps;
}
Оба события необходимы, потому что новые сущности инициируют события Tracked, когда они отслеживаются впервые.
StateChanged события запускаются только для сущностей, которые изменяют состояние, пока они уже отслеживаются.
Пример этого примера содержит простое консольное приложение, которое вносит изменения в базу данных блогов:
using (var context = new BlogsContext())
{
await context.Database.EnsureDeletedAsync();
await context.Database.EnsureCreatedAsync();
context.Add(
new Blog
{
Id = 1,
Name = "EF Blog",
Posts = { new Post { Id = 1, Title = "EF Core 3.1!" }, new Post { Id = 2, Title = "EF Core 5.0!" } }
});
await context.SaveChangesAsync();
}
using (var context = new BlogsContext())
{
var blog = await context.Blogs.Include(e => e.Posts).SingleAsync();
blog.Name = "EF Core Blog";
context.Remove(blog.Posts.First());
blog.Posts.Add(new Post { Id = 3, Title = "EF Core 6.0!" });
await context.SaveChangesAsync();
}
В выходных данных этого кода отображаются изменения состояния и примененные метки времени:
Stamped for insert: Blog 1 Added on: 10/15/2020 11:01:26 PM
Stamped for insert: Post 1 Added on: 10/15/2020 11:01:26 PM
Stamped for insert: Post 2 Added on: 10/15/2020 11:01:26 PM
Stamped for delete: Post 1 Added on: 10/15/2020 11:01:26 PM Deleted on: 10/15/2020 11:01:26 PM
Stamped for update: Blog 1 Added on: 10/15/2020 11:01:26 PM Modified on: 10/15/2020 11:01:26 PM
Stamped for insert: Post 3 Added on: 10/15/2020 11:01:26 PM