使用 Entity Framework Core,我需要检查实体内导航属性的原始值,但我找不到方法来执行此操作。
我能够读取实际实体及其引用属性的原始值和当前值,但当我读取导航属性时,OriginalValue 属性丢失。
这是我到目前为止所能做的。
var entries = ChangeTracker.Entries<Book>()
.Where(x => x.State == EntityState.Modified)
.ToList();
foreach (var entry in entries)
{
// read the entity current & original values
var currentTitleValue = entry.Property(x => x.Title).CurrentValue;
var originalTitleValue = entry.Property(x => x.Title).OriginalValue;
// read the reference object current & original values
var promotionReferenceEntry = entry.Reference(x => x.Promotion);
var currentPromotionPriceValue = promotionReferenceEntry.TargetEntry.Property(x => x.Price).CurrentValue;
var originalPromotionPriceValue = promotionReferenceEntry.TargetEntry.Property(x => x.Price).OriginalValue;
// read the navigation object current & original values
var authorsCollectionEntry = entry.Collection(x => x.AuthorBooks);
var currentAuthorIds = authorsCollectionEntry.CurrentValue.Select(x => x.AuthorId).ToList();
var originalAuthorIds = ?????;
}
这是一种获取上下文中的引用属性及其原始值的方法:
var entries = ChangeTracker.Entries<Book>()
.Where(x => x.State == EntityState.Modified)
.ToList();
foreach (var entry in entries)
{
// If it is Added/Deleted, you can't get the OriginalValues/CurrentValues respectively.
// So make it Modified for the meanwhile.
var tempState = entry.State;
entry.State = EntityState.Modified;
// Clone the Entity values (the original ID, Current ID of the navigation
var currentValues = Entry(entry.Entity).CurrentValues.Clone();
var originalValues = Entry(entry.Entity).OriginalValues.Clone();
// Set the Entity values to the OriginalValues and load the reference
Entry(entry.Entity).CurrentValues.SetValues(originalValues);
Entry(entry.Entity).Reference(x => x.Promotion).Load();
// Store the Original Reference value in a variable
var promotionReferenceEntryOriginalValue = entry.Reference(x => x.Promotion).CurrentValue;
// Set the Entity values back to CurrentValues and load the reference
Entry(entry.Entity).CurrentValues.SetValues(currentValues);
Entry(entry.Entity).Reference(x => x.Promotion).Load();
// Store the Current Reference value in a variable
var promotionReferenceEntryCurrentValue = entry.Reference(x => x.Promotion).CurrentValue;
// Set the Entry State back to its original State Added/Modified/Deleted
entry.State = tempState;
// read the entity current & original values
var currentTitleValue = entry.Property(x => x.Title).CurrentValue;
var originalTitleValue = entry.Property(x => x.Title).OriginalValue;
// read the reference object current & original values
//var promotionReferenceEntry = entry.Reference(x => x.Promotion);
var currentPromotionPriceValue = promotionReferenceEntryCurrentValue.Price; // promotionReferenceEntry.TargetEntry.Property(x => x.Price).CurrentValue;
var originalPromotionPriceValue = promotionReferenceEntryOriginalValue.Price; // promotionReferenceEntry.TargetEntry.Property(x => x.Price).OriginalValue;
}
要使其动态化,请从
<Book>
中删除类型 ChangeTracker.Entries<Book>()
并循环遍历 entry.Entity
循环内的 foreach (var entry in entries)
属性:
foreach (var propertyInfo in entry.Entity.GetType().GetProperties())
{
var propertyName = propertyInfo.Name;
//Do the loads here...
//Get the values
}
通过尝试使用额外的方法访问它来检查它是否是导航引用或集合引用,并检查它是否为空,不为空意味着它是一个有效的属性,可以尝试并
load()
它:
private DbPropertyEntry GetProperty(DbEntityEntry entry, string propertyName)
{
try
{
return entry.Property(propertyName);
}
catch { return null; }
}
private DbReferenceEntry GetReference(DbEntityEntry entry, string propertyName)
{
try
{
return entry.Reference(propertyName);
}
catch { return null; }
}
private DbCollectionEntry GetCollection(DbEntityEntry entry, string propertyName)
{
try
{
return entry.Collection(propertyName);
}
catch { return null; }
}
https://github.com/dotnet/efcore/issues/9050
原始值是查询实体时数据库中存在的值。因此对于关系来说,FK属性将具有原始值。导航属性是根据 FK 值合成的,而不是直接映射到数据库中的任何内容。这意味着导航属性(引用和集合)没有原始值。