Теневые Свойства в Entity Framework Core
Множество моделей, перегружено свойствами, которые на самом деле не обязательно в них включать. Вместо этого мы можем использовать теневые свойства, чтобы сохранить чистоту модели и включать в неё только те свойства, которые относятся к предметной области.
Вариантом использования теневых свойств являются столбцы аудита, например
CreatedOn, CreatedBy и т.п. Или столбцы периода из темпоральной таблицы. Эти столбцы полезны для отслеживания того, кто создал или обновил запись, но они не добавляют никакой ценности сущности домена.Другой вариант использования — свойства, которые содержат ссылку на внешний ключ, или свойства навигации. Это очень путает, потому что неясно, какое свойство использовать. Например:
class CustomerМы можем сказать Entity Framework создать теневое свойство AddressId и добавить необходимые ограничения отношений.
{
// внешний ключ
public Guid AddressId { get; set; }
// навигационное свойство
public Address Address { get; set; }
}
Рассмотрим пример создания теневого свойства для «мягкого удаления»:
protected override voidЧтобы устанавливать и обновлять значения теневого свойства, получите EntityEntry сущности и используйте метод Property:
OnModelCreating(ModelBuilder mb)
{
mb.Entity<Customer>()
.Property<DateTime?>("DeletedOn");
mb.Entity<Customer>()
.HasQueryFilter(e =>
EF.Property<DateTime?>(e, "DeletedOn") == null);
}
dbContextЭто более полезно, когда не нужно думать об этих свойствах, а они устанавливаются автоматически. Этого можно добиться, переопределив метод SaveChanges объекта DbContext:
.Entry(customer)
.Property("DeletedOn")
.CurrentValue = DateTime.UtcNow;
dbContext.SaveChanges();
public class DemoDbContext : DbContextИсточник: https://timdeschryver.dev/blog/entity-framework-features-i-wish-i-knew-earlier#shadow-properties
{
public override int SaveChanges()
{
ChangeTracker.DetectChanges();
foreach (var e in
ChangeTracker.Entries())
{
if (e.State == EntityState.Added)
e.Property("CreatedOn")
.CurrentValue = DateTime.UtcNow;
if (e.State == EntityState.Modified)
e.Property("UpdatedOn")
.CurrentValue = DateTime.UtcNow;
if (e.State == EntityState.Deleted)
e.Property("DeletedOn")
.CurrentValue = DateTime.UtcNow;
}
return base.SaveChanges();
}
}