Does an entity model fire an event when its data changes?
I want to be notified when data changes within a particular table, represented by an entity model. Is 开发者_如何学编程the model aware of underlying data changes? If it does actually fire an event, how can I subscribe to it?
Your question is actually very unclear.
I want to be notified when data changes within a particular table, represented by an entity model.
What does it mean?
Do you want to be notified about changes in database not done by your application? Then the answer is: No EF doesn't provide any such notification system. You must build your own.
Do you want to be notified about changes you did to your entities? The the answer is INotifyPropertyChanged interface and ObservableCollection for navigation properties. use these constructs in your entities to be able to fire events when entity changes.
Do you want to know what changes will be executed in the database? Override SaveChanges
or handle SavingChanges
and use ObjectStateManager
to get list of changed entities. Here is some example how to get list of added entities of given type.
The NuGet package EntityFramework.Triggers nicely wraps up functionality of subscribing to an Entity for inserts, updates, and deletions.
Just wrap your context with the DbContextWithTriggers;
public class MyContext : DbContextWithTriggers {
public DbSet<Person> People { get; set; }
}
Then subscribe to trigger events
var mycontext = new MyContext() { TriggersEnabled = true };
Triggers<Person>.Inserting += entry =>
{
Console.WriteLine($"Person: {entry.Entity}");
};
No, there is no events fired on Change
, only when you do SaveChanges
you could catch what you need ...
for that, try looking at this question / answers
you can use Interceptors.
just inherit SaveChangesInterceptor
and override
SavingChangesAsync
then listen SavedChanges
event.
you should override
SavingChanges
,because in SavedChanges
all entry.State
is EntityState.Unchanged
My code is just like this:
public override InterceptionResult<int> SavingChanges(DbContextEventData eventData, InterceptionResult<int> result)
{
try
{
foreach (var entry in eventData.Context.ChangeTracker.Entries())
{
//when target entity is modified ,subscribe event
if (entry.Entity is Device de && (entry.State == EntityState.Added || entry.State == EntityState.Deleted || entry.State == EntityState.Modified))
{
if (entry.State == EntityState.Modified)
{
if (de.UseStatus.GetValueOrDefault(0) != (int)UseStatusConstType.IsCancel)
{
continue;
}
}
ModifiedDeviceId = de.Id;
eventData.Context.SavedChanges -= Context_SavedChangesAsync;
eventData.Context.SavedChanges += Context_SavedChangesAsync;
}
}
return result;
}
catch (Exception ex)
{
_log.LogError(ex, "when entryState changing,try auto run function faild");
return result;
}
}
private async void Context_SavedChangesAsync(object sender, SavedChangesEventArgs e)
{
//_log.LogInformation("current ModifiedDeviceId is {ModifiedDeviceId} ", ModifiedDeviceId);
try
{
_log.LogInformation("in logger:{logger} for device:{deviceId},the state changed,now refresh device cache ", nameof(AutoRefreshDeviceCacheInterceptor), ModifiedDeviceId);
//just do you want
}
catch (Exception ex)
{
_log.LogError(ex, "in logger:{logger} after entryState changed,try auto run function faild", nameof(AutoRefreshDeviceCacheInterceptor));
}
}
public override async ValueTask<InterceptionResult<int>> SavingChangesAsync(DbContextEventData eventData, InterceptionResult<int> result, CancellationToken cancellationToken = default)
{
try
{
eventData.Context.ChangeTracker.DetectChanges();
foreach (var entry in eventData.Context.ChangeTracker.Entries())
{
if (entry.Entity is Device de && (entry.State == EntityState.Added || entry.State == EntityState.Deleted || entry.State == EntityState.Modified))
{
if (entry.State == EntityState.Modified)
{
if (de.UseStatus.GetValueOrDefault(0) != (int)UseStatusConstType.IsCancel)
{
continue;
}
}
ModifiedDeviceId = de.Id;
eventData.Context.SavedChanges -= Context_SavedChangesAsync;
eventData.Context.SavedChanges += Context_SavedChangesAsync;
}
}
return result;
}
catch (Exception ex)
{
_log.LogError(ex, "when entryState changing,try auto run function faild");
return result;
}
}
精彩评论