EF Core의 .NET 이벤트
팁
이벤트 샘플은 GitHub에서 다운로드할 수 있습니다.
EF Core(Entity Framework Core)는 EF Core 코드에서 특정 작업을 수행하는 경우 콜백을 수행할 .NET 이벤트를 노출합니다. 이벤트는 인터셉터보다 간단하며 더 유연하게 등록할 수 있습니다. 그러나 동기화 전용이므로 비차단 비동기 I/O를 수행할 수 없습니다.
이벤트는 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())
{
context.Database.EnsureDeleted();
context.Database.EnsureCreated();
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!" } }
});
context.SaveChanges();
}
using (var context = new BlogsContext())
{
var blog = context.Blogs.Include(e => e.Posts).Single();
blog.Name = "EF Core Blog";
context.Remove(blog.Posts.First());
blog.Posts.Add(new Post { Id = 3, Title = "EF Core 6.0!" });
context.SaveChanges();
}
이 코드의 출력은 발생하는 상태 변경 내용과 적용되는 타임스탬프를 보여 줍니다.
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
.NET