Eventos de .NET en EF Core
Sugerencia
Puede descargar el ejemplo de eventos de GitHub.
Entity Framework Core (EF Core) expone eventos de .NET para que actúen como devoluciones de llamada cuando ocurran ciertas cosas en el código EF Core. Los eventos son más sencillos que los interceptores y permiten un registro más flexible. Sin embargo, solo son sincrónicos y, por tanto, no pueden realizar operaciones de E/S asincrónicas sin bloqueo.
Los eventos se registran por instancia de DbContext
. Use una escucha de diagnóstico para obtener la misma información, pero para todas las instancias de DbContext del proceso.
Eventos generados por EF Core
EF Core genera los siguientes eventos:
Evento | Cuando se genera |
---|---|
DbContext.SavingChanges | Al principio de SaveChanges o SaveChangesAsync |
DbContext.SavedChanges | Al final de una operación correcta SaveChanges o SaveChangesAsync |
DbContext.SaveChangesFailed | Al final de una SaveChanges o SaveChangesAsync con errores |
ChangeTracker.Tracked | Cuando el contexto realiza un seguimiento de una entidad |
ChangeTracker.StateChanged | Cuando una entidad con seguimiento cambia su estado |
Ejemplo: cambios de estado de marca de tiempo
Cada entidad de la que realiza un seguimiento DbContext tiene un EntityState. Por ejemplo, el estado Added
indica que la entidad se insertará en la base de datos.
En este ejemplo se usan los eventos Tracked y StateChanged para detectar cuándo cambia el estado de una entidad. A continuación, marca la entidad con la hora actual que indica cuándo se produjo este cambio. Esto da como resultado marcas de tiempo que indican cuándo se insertó, eliminó o actualizó por última vez la entidad.
Los tipos de entidad de este ejemplo implementan una interfaz que define las propiedades de marca de tiempo:
public interface IHasTimestamps
{
DateTime? Added { get; set; }
DateTime? Deleted { get; set; }
DateTime? Modified { get; set; }
}
A continuación, un método de DbContext de la aplicación puede establecer marcas de tiempo para cualquier entidad que implemente esta interfaz:
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;
}
}
}
Este método tiene la firma adecuada para usar como controlador de eventos para los eventos Tracked
y StateChanged
. El controlador se registra para ambos eventos en el constructor DbContext. Tenga en cuenta que los eventos se pueden adjuntar a DbContext en cualquier momento; no es necesario que esto suceda en el constructor de contexto.
public BlogsContext()
{
ChangeTracker.StateChanged += UpdateTimestamps;
ChangeTracker.Tracked += UpdateTimestamps;
}
Ambos eventos son necesarios porque las nuevas entidades activan eventos Tracked
cuando se realiza el seguimiento por primera vez. Los eventos StateChanged
solo se activan para las entidades que cambian de estado cuando ya se están supervisando.
El ejemplo de este ejemplo contiene una aplicación de consola sencilla que realiza cambios en la base de datos de registro:
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();
}
La salida de este código muestra los cambios de estado que se producen y las marcas de tiempo que se aplican:
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