Entity Framework 6: изменения аудита/отслеживания
У меня есть основной проект на С#.
Я работаю над базой данных, где в некоторых таблицах есть столбцы "user_mod" и "date_mod" для знака, кто и когда сделал несколько модов и то же самое с "data_new" и "user_new".
Мой вопрос: есть ли способ централизовать это и вставить эти данные автоматически, где я создаю экземпляр dbContext
?
Если нет, я буду использовать инструмент аудита. Я видел некоторые из них, но есть проблема: все это требует некоторого кода в моей модели. Но я не хочу писать в своей модели, потому что, если мне нужно ее изменить, я потеряю моды. Возможно ли использовать контрольный журнал для EF6 без записи в файле модели? Как?
EDIT:
Моя попытка переопределить saveChanges.
public partial class PieEntities : DbContext
{
public override int SaveChanges(System.Data.Objects.SaveOptions options)
{
var timestamp = DateTime.Now;
EntityState es = EntityState.Added;
ObjectStateManager o = new ObjectStateManager();
foreach (ObjectStateEntry entry in o.GetObjectStateEntries(EntityState.Added )) {
if (entry.Entity.GetType() == typeof(TabImpianti)) {
TabImpianti impianto = entry.Entity as TabImpianti;
impianto.DATA_INS = timestamp;
impianto.DATA_MOD = timestamp;
string u = mdlImpostazioni.p.UserName;
impianto.USER_INS = u;
impianto.USER_MOD = u;
}
}
return base.SaveChanges(options);
}
}
ОБНОВЛЕНИЕ: я подвел итоги здесь.
Ответы
Ответ 1
Если вы используете EF6 DbContext
, вы можете использовать переопределение ChangeTracker
в SaveChanges
для поиска добавленных/измененных объектов пользовательского типа, например IAuditedEntity.
public interface IAuditedEntity {
string CreatedBy { get; set; }
DateTime CreatedAt { get; set; }
string LastModifiedBy { get; set; }
DateTime LastModifiedAt { get; set; }
}
public override int SaveChanges() {
var addedAuditedEntities = ChangeTracker.Entries<IAuditedEntity>()
.Where(p => p.State == EntityState.Added)
.Select(p => p.Entity);
var modifiedAuditedEntities = ChangeTracker.Entries<IAuditedEntity>()
.Where(p => p.State == EntityState.Modified)
.Select(p => p.Entity);
var now = DateTime.UtcNow;
foreach (var added in addedAuditedEntities) {
added.CreatedAt = now;
added.LastModifiedAt = now;
}
foreach (var modified in modifiedAuditedEntities) {
modified.LastModifiedAt = now;
}
return base.SaveChanges();
}
Ответ 2
Существует пакет nuget для этого
https://www.nuget.org/packages/TrackerEnabledDbContext
Источник:
https://github.com/bilal-fazlani/tracker-enabled-dbcontext
Ответ 3
Есть один способ сделать это: вы можете создать частичный класс с тем же именем, что и ваш объектный контекст, и реализовать переопределение метода SaveChanges
. В этом переопределении вы можете просмотреть все изменения, которые будут перенесены в БД и обработать их.
Вы можете обрабатывать их любым способом, как вам нравится, в следующем примере я создал интерфейс IAutoTimestampEntity
, содержащий дату создания и дату модификации. Любой объект этого типа будет автоматически обновляться со временем изменения.
public override int SaveChanges(System.Data.Objects.SaveOptions options)
{
var timestamp = DateTime.Now;
foreach (var InsertedAutoTimestampEntity in ObjectStateManager.GetObjectStateEntries(System.Data.EntityState.Added).Select(ose => ose.Entity).OfType<IAutoTimestampEntity>())
{
InsertedAutoTimestampEntity.CreationDate = timestamp;
InsertedAutoTimestampEntity.ModificationDate = timestamp;
}
foreach (var UpdatedAutoTimestampEntity in ObjectStateManager.GetObjectStateEntries(System.Data.EntityState.Modified).Select(ose => ose.Entity).OfType<IAutoTimestampEntity>())
{
UpdatedAutoTimestampEntity.ModificationDate = timestamp;
}
return base.SaveChanges(options);
}
Вы можете использовать тот же принцип, или можете подробно просмотреть тип каждого измененного объекта. Мне нравится декларативный аспект интерфейса. Это позволяет вам явно разоблачить один аспект автоматизации, а не позволять его делать тихо на уровне EF.
Если у вас есть DbContext
вместо ObjectContext
, откройте DbContext
до IObjectContextAdapter
, чтобы получить доступ к ObjectStateManager