В настоящее время я пытаюсь использовать Entity Framework ChangeTracker для целей аудита. Я переопределяю метод SaveChanges() в своем DbContext и создаю журналы для объектов, которые были добавлены, изменены или удалены. Вот код для этого FWIW:
public override int SaveChanges()
{
var validStates = new EntityState[] { EntityState.Added, EntityState.Modified, EntityState.Deleted };
var entities = ChangeTracker.Entries().Where(x => x.Entity is BaseEntity && validStates.Contains(x.State));
var entriesToAudit = new Dictionary<object, EntityState>();
foreach (var entity in entities)
{
entriesToAudit.Add(entity.Entity, entity.State);
}
//Save entries first so the IDs of new records will be populated
var result = base.SaveChanges();
createAuditLogs(entriesToAudit, entityRelationshipsToAudit, changeUserId);
return result;
}
Это отлично подходит для "нормальных" объектов. Однако для простых отношений "многие-ко-многим" мне пришлось расширить эту реализацию, включив в нее "Независимые ассоциации", как описано в этом > фантастическом SO-ответе, который обращается к изменениям через ObjectContext так:
private static IEnumerable<EntityRelationship> GetRelationships(this DbContext context, EntityState relationshipState, Func<ObjectStateEntry, int, object> getValue)
{
context.ChangeTracker.DetectChanges();
var objectContext = ((IObjectContextAdapter)context).ObjectContext;
return objectContext
.ObjectStateManager
.GetObjectStateEntries(relationshipState)
.Where(e => e.IsRelationship)
.Select(
e => new EntityRelationship(
e.EntitySet.Name,
objectContext.GetObjectByKey((EntityKey)getValue(e, 0)),
objectContext.GetObjectByKey((EntityKey)getValue(e, 1))));
}
После внедрения это также отлично работает, , но только для отношений "многие-ко-многим", которые используют таблицу соединений. Таким образом, я имею в виду ситуацию, когда отношения не представлены классом/сущностью, а только таблица базы данных с двумя столбцами - по одному для каждого внешнего ключа.
В моей модели данных существуют определенные отношения "многие ко многим" , однако, когда отношение имеет "поведение" (свойства). В этом примере ProgramGroup
- это отношение "многие ко многим" , которое имеет свойство Pin
:
public class Program
{
public int ProgramId { get; set; }
public List<ProgramGroup> ProgramGroups { get; set; }
}
public class Group
{
public int GroupId { get; set; }
public IList<ProgramGroup> ProgramGroups { get; set; }
}
public class ProgramGroup
{
public int ProgramGroupId { get; set; }
public int ProgramId { get; set; }
public int GroupId { get; set; }
public string Pin { get; set; }
}
В этой ситуации я не вижу изменения в ProgramGroup
(например, если Pin изменяется) в "нормальном" DbContext ChangeTracker или методе отношений ObjectContext. Однако, когда я просматриваю код, я вижу, что это изменение находится в объекте ObjectContext StateEntries, но его запись имеет IsRelationship=false
, что, конечно же, не соответствует условию .Where(e => e.IsRelationship)
.
Мой вопрос в том, почему существует отношение "многие ко многим" с поведением, которое не появляется в обычном DbContext ChangeTracker, поскольку оно представлено фактическим классом/сущностью и почему оно не помечено как отношение в ObjectContext StateEntries? Кроме того, какова наилучшая практика для доступа к этим типам изменений?
Спасибо заранее.
EDIT:
В ответ на комментарий @FrancescCastells, что, возможно, не явное определение конфигурации для ProgramGroup
является причиной проблемы, я добавил следующую конфигурацию:
public class ProgramGroupConfiguration : EntityTypeConfiguration<ProgramGroup>
{
public ProgramGroupConfiguration()
{
ToTable("ProgramGroups");
HasKey(p => p.ProgramGroupId);
Property(p => p.ProgramGroupId).IsRequired();
Property(p => p.ProgramId).IsRequired();
Property(p => p.GroupId).IsRequired();
Property(p => p.Pin).HasMaxLength(50).IsRequired();
}
И вот мои другие конфигурации:
public class ProgramConfiguration : EntityTypeConfiguration<Program>
{
public ProgramConfiguration()
{
ToTable("Programs");
HasKey(p => p.ProgramId);
Property(p => p.ProgramId).IsRequired();
HasMany(p => p.ProgramGroups).WithRequired(p => p.Program).HasForeignKey(p => p.ProgramId);
}
}
public class GroupConfiguration : EntityTypeConfiguration<Group>
{
public GroupConfiguration()
{
ToTable("Groups");
HasKey(p => p.GroupId);
Property(p => p.GroupId).IsRequired();
HasMany(p => p.ProgramGroups).WithRequired(p => p.Group).HasForeignKey(p => p.GroupId);
}
Когда они реализованы, EF по-прежнему не показывает измененный ProgramGroup
в ChangeTracker.