简体   繁体   中英

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 ObservableCollectio n 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

If you purpose is to save data only in case there are changes then refer to the following link:

http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext.savingchanges.aspx

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;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM