TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.77K subscribers
Post #2046 1.74K
День 1689. #TipsAndTricks
Теневые Свойства в Entity Framework Core
Множество моделей, перегружено свойствами, которые на самом деле не обязательно в них включать. Вместо этого мы можем использовать теневые свойства, чтобы сохранить чистоту модели и включать в неё только те свойства, которые относятся к предметной области.

Вариантом использования теневых свойств являются столбцы аудита, например CreatedOn, CreatedBy и т.п. Или столбцы периода из темпоральной таблицы. Эти столбцы полезны для отслеживания того, кто создал или обновил запись, но они не добавляют никакой ценности сущности домена.

Другой вариант использования — свойства, которые содержат ссылку на внешний ключ, или свойства навигации. Это очень путает, потому что неясно, какое свойство использовать. Например:
class Customer
{
// внешний ключ
public Guid AddressId { get; set; }

// навигационное свойство
public Address Address { get; set; }
}
Мы можем сказать Entity Framework создать теневое свойство AddressId и добавить необходимые ограничения отношений.

Рассмотрим пример создания теневого свойства для «мягкого удаления»:
protected override void 
OnModelCreating(ModelBuilder mb)
{
mb.Entity<Customer>()
.Property<DateTime?>("DeletedOn");

mb.Entity<Customer>()
.HasQueryFilter(e =>
EF.Property<DateTime?>(e, "DeletedOn") == null);
}

Чтобы устанавливать и обновлять значения теневого свойства, получите EntityEntry сущности и используйте метод Property:
dbContext
.Entry(customer)
.Property("DeletedOn")
.CurrentValue = DateTime.UtcNow;
dbContext.SaveChanges();

Это более полезно, когда не нужно думать об этих свойствах, а они устанавливаются автоматически. Этого можно добиться, переопределив метод SaveChanges объекта DbContext:
public class DemoDbContext : DbContext
{
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();
}
}

Источник: https://timdeschryver.dev/blog/entity-framework-features-i-wish-i-knew-earlier#shadow-properties
  • 👍 18
More from @netdeveloperdiary
  1. Oct 10, 2026День 2810. #ЧтоНовенького #VSCode Более Быстрый и Лёгкий C# Dev Kit Мы, разработчики, люби…
  2. Oct 9, 2026День 2809. #Карьера 5 Навыков, Которые Помогут Быстрее Стать Сеньором. Окончание Начало 3.…
  3. Oct 8, 2026День 2808. #Карьера 5 Навыков, Которые Помогут Быстрее Стать Сеньором. Начало В ИТ есть се…
  4. Oct 7, 2026День 2807. #ЗаметкиНаПолях Типы Коллекций в .NET, Которые Стоит Попробовать. Окончание Нач…
  5. Oct 6, 2026🦈 Открытое собеседование на Middle C# | 6 октября, 19:00 МСК Приглашаем на открытое собес…
  6. Oct 6, 2026День 2806. #ЗаметкиНаПолях Типы Коллекций в .NET, Которые Стоит Попробовать. Начало Больши…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →