简体   繁体   English

实体 model 是否在其数据更改时触发事件?

[英]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.我想在特定表中的数据更改时收到通知,由实体 model 表示。 Is the model aware of underlying data changes? model 是否知道底层数据更改? 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. 然后答案是:没有EF不提供任何此类通知系统。 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. 答案是INotifyPropertyChanged接口和ObservableCollectio n用于导航属性。 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. 覆盖SaveChanges或处理SavingChanges并使用ObjectStateManager获取已更改实体的列表。 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. NuGet包EntityFramework.Triggers很好地包含了订阅实体以进行插入,更新和删除的功能。

Just wrap your context with the DbContextWithTriggers; 用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 ... 不,没有事件在Change上被触发,只有当你做SaveChanges你才能捕捉到你需要的东西......

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 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.只需继承SaveChangesInterceptoroverride SavingChangesAsync然后监听SavedChanges事件。

you should override SavingChanges ,because in SavedChanges all entry.State is EntityState.Unchanged你应该override SavingChanges ,因为在SavedChanges所有entry.StateEntityState.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;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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