Here is a way to get the reference properties in the context as well as its original values:
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;
}
To make it dynamic, remove the type <Book>
from ChangeTracker.Entries<Book>()
and loop though the entry.Entity
properties inside the foreach (var entry in entries)
loop:
foreach (var propertyInfo in entry.Entity.GetType().GetProperties())
{
var propertyName = propertyInfo.Name;
//Do the loads here...
//Get the values
}
Check if it is a navigation reference or a collection reference by trying to access it using extra methods and check if it is null or not, not null means it is a valid property to try and load()
it:
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; }
}
entry
? – Maiolicacontext.Entry(entry.Entity).Reference(x => x.Promotion).Load();
then afterwards have the values. To get the current and original values from the reference property, had to first create temp vars and clone the current/original values, set the original values as current values on theentity
then load the reference to get the original values, set theEntity
current values back to the cloned current values, load the reference to get its current values, done. You can temp modify state as well for Add/Delete – Misrepresent