Недавно я изучал EF Core на основе Audit ChangeLog, где я нашел большую часть ресурсов, которые отслеживают журнал как прямое свойство сущности, используя отражение, предположим, у меня есть две связанные сущности:
public Class Order
{
public int OrderId {get; set;}
public int OrderName {get; set;}
public virtual Collection<OrderDetail> OrderDetails { get; set; } = new Collection<OrderDetail>();
}
public Class OrderDetail
{
public int OrderDetailId {get; set;}
public int OrderDetailName {get; set;}
public int OrderDetailQuantity {get; set;}
public int? OrderID { get; set; }
public virtual Order OrderFk { get; set; }
}
Тогда мой TrackChange будет выглядеть следующим образом:
protected virtual IEnumerable<ChangeLog> TrackChange()
{
foreach (var entry in DbContext.ChangeTracker.Entries())
{
var entityType = entry.Entity.GetType();
foreach (var property in entityType.GetTypeInfo().DeclaredProperties)
{
var originalValue = entry.Property(property.Name).OriginalValue;
var currentValue = entry.Property(property.Name).CurrentValue;
//Log if originalValue != currentValue
}
}
}
Поэтому, если у меня есть Order, содержащий 3 OrderDetails, тогда я изменяю Name Order и один из OrderDetail, обновляя OrderDetailQuantity. и сохранить как Order, TrackChange перехватит мое изменение OrderName, так как это свойство Order, но , когда «свойство в entityType.GetTypeInfo (). DeclaredProperties» становится «OrderDetails» , это делаетне достаточно умен, чтобы обнаружить, что это коллекция или связанная сущность «Порядка», тогда я получаю исключение при попытке получить originalValue, говоря:
'The property 'OrderDetails' on entity type 'Order' is being accessed using the 'Property' method, but is defined in the model as a navigation property. Use either the 'Reference' or 'Collection' method to access navigation properties.'
Я знаю, что, вероятно, могу использовать entry.Collection (свойство.Имя), чтобы перейти в коллекцию "OrderDetail", но вопрос будет: Откуда мне знать, что текущая собственностьy является типом значения типа Int / String / Datetime, хотя он также может быть связанной сущностью или коллекцией текущей записи?
Другие мысли о TrackChange и ниже - моя идея псевдокода:
function TrackChange(Entity)
//Track Base Entity Change
...
//Track Child Entity Change if there is any
if (Entity.HasChildNode)
{
foreach(ChildEntity of Entity.ChildEntities)
TrackChange(ChildEntity);
}
...
}
Поскольку мой TrackChange является универсальным, поэтому я надеюсь, что есть способ реализовать вышеуказанную идею, используя отражение C #.