I need to get the list of changed fields only, the datastore is ssce so no triggers are available
Is there any support in EF to get a list or to build a generic component ?
By default, EF Core creates a snapshot of every entity's property values when it is first tracked by a DbContext instance. The values stored in this snapshot are then compared against the current values of the entity in order to determine which property values have changed.
EF Core change tracking works best when the same DbContext instance is used to both query for entities and update them by calling SaveChanges. This is because EF Core automatically tracks the state of queried entities and then detects any changes made to these entities when SaveChanges is called.
Depending on the type of context and generated entities you can do it in several different ways.
In case of objects inherited from Entity or POCO you can use ObjectStateManager
in case of Self-Tracking entities you can use Tracker from entity itself.
please provide more details on the way how you generated context and how you make changes
EDITED(2):
you can query ObjectStateManager
for changed entries simply like this:
var changed = ctx.ObjectStateManager.GetObjectStateEntries().Where(e=>e.State != EntityState.Unchanged);
EDITED(1):
The following example from MSDN demonstrate how to query for changes:
int orderId = 43680;
using (AdventureWorksEntities context =
new AdventureWorksEntities())
{
var order = (from o in context.SalesOrderHeaders
where o.SalesOrderID == orderId
select o).First();
// Get ObjectStateEntry from EntityKey.
ObjectStateEntry stateEntry =
context.ObjectStateManager
.GetObjectStateEntry(((IEntityWithKey)order).EntityKey);
//Get the current value of SalesOrderHeader.PurchaseOrderNumber.
CurrentValueRecord rec1 = stateEntry.CurrentValues;
string oldPurchaseOrderNumber =
(string)rec1.GetValue(rec1.GetOrdinal("PurchaseOrderNumber"));
//Change the value.
order.PurchaseOrderNumber = "12345";
string newPurchaseOrderNumber =
(string)rec1.GetValue(rec1.GetOrdinal("PurchaseOrderNumber"));
// Get the modified properties.
IEnumerable<string> modifiedFields = stateEntry.GetModifiedProperties();
foreach (string s in modifiedFields)
Console.WriteLine("Modified field name: {0}\n Old Value: {1}\n New Value: {2}",
s, oldPurchaseOrderNumber, newPurchaseOrderNumber);
// Get the Entity that is associated with this ObjectStateEntry.
SalesOrderHeader associatedEnity = (SalesOrderHeader)stateEntry.Entity;
Console.WriteLine("Associated Enity's ID: {0}", associatedEnity.SalesOrderID);
}
It's commonly a good practice to do this by using the database structure itself. This is just another approach to the one you have now.
You can create a new field of type datetime
in a table called for example ModifiedOn
and update it every time that you update the row in the database.
Then when you want the changed rows after a specific time you just use:
where ModifiedOn > dateTime
It's just another suggestion on how you can approach the problem from a different angle.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With