У моей сущности есть это:
public DateTime UpdatedAt { get; private set; }
Я хочу обновлять это свойство каждый раз, когда обновляю сущность, поэтому у меня есть это:
private void updateTimeStamp() => UpdatedAt = DateTime.UtcNow;
Но тогда мне нужно запомнитьвызывать его в каждом методе, который мутирует сущность, например:
public void addOrder(Order order) {
//blah blah
updateTimeStamp(); // <----- musn't forget this!
}
Я часто забываю вызывать этот метод, поэтому я думаю об альтернативах.Я не знаю, что лучше, или если есть что-то, что я не учел.
Вариант 1: инициализировать свойство
public DateTime UpdatedAt { get; private set; } = DateTime.UtcNow;
Проблема: это будетустанавливается каждый раз, даже если я не хочу обновлять сущность.
Опция 2: атрибуты
[UpdateTimestamp]
public void addOrder(Order order) {
//blah blah
}
Проблема: это не улучшаетситуация, в основном, такая же, как исходная проблема.
Вариант 3: автоматическое обновление в context.SaveChanges()
ChangeTracker.Entries()
.Where(e => e.Entity is MyEntity)
.Where(e => e.State == EntityState.Modified)
.Where(e => e.Entity as MyEntity)
.ToList()
.ForEach(e => { e.UpdatedAt = DateTime.UtcNow; });
Проблема: UpdatedAt
теперь нужна общедоступнаясеттер.Это нарушает принципы DDD.Это самый простой вариант, но это означает, что я должен отказаться от DDD "всегда действительным".
Опция 3: то же, что 3, но с использованием отражения
Подобно варианту 3, я мог бы использоватьотражение, чтобы изменить свойство, даже если у него есть частный сеттер.Это достаточно легко сделать, и тот факт, что это отражение и «медленный», не имеет большого значения, так как время будет незначительным по сравнению с записью в базу данных.
Проблема: сделать изменения в инфраструктуре, а недомен просто кажется неправильным.
В противном случае это довольно хороший выбор.Это не чистый DDD, но, по крайней мере, он позволяет мне защитить инварианты сущности.
Вариант 4: разгрузка на провайдера БД или самой БД
builder.Property(e => e.UpdatedAt).ValueGeneratedOnUpdate();
// or
builder.Property(e => e.UpdatedAt).HasComputedColumnSql("GETDATE()");
Проблема:не работает для всех провайдеров (не работает для меня, потому что я использую Npgsql, который не поддерживает вычисляемые столбцы).Также это перемещает проблему в инфраструктуру и из домена.Поэтому я чувствую, что снова ломаю DDD.
Итак ... что-то я забыл?Если вы делаете DDD, как вы справляетесь с этим?