实体状态更改时收到通知

时间:2014-05-28 02:22:54

标签: mysql winforms entity-framework

我正在构建一个使用Entity Framework(版本6)来管理持久性的应用程序。这对我来说很新,但到目前为止,我对此印象非常深刻。

我有一个问题,由于被无关的答案所淹没,我似乎无法在网上找到答案。基本上我有表格向用户显示实体的细节以进行编辑。我想要做的是根据实体的状态(或更准确地说是DbEntityEntry)启用和禁用“保存更改”按钮。

我可以从Context确定实体的状态,因此确定状态不是问题。它知道状态何时改变,我遇到了麻烦。因此,可以从数据存储中加载实体并呈现该实体,并且最初将处于未更改状态。一旦用户开始编辑表单数据,实体就会被修改(由于数据绑定)。

我应该在哪里联系以获得对实体变更的通知?我是否应该挂钩每个控件的更改事件或绑定源更改事件或其他事件?

详细说明: 实体框架6,WinForms,MySql数据存储区

2 个答案:

答案 0 :(得分:0)

如果您实现类似的实体类:

public class Person
{
    public virtual int Id { get; set; }
    public virtual string SomeProperty { get; set; }
}

所以类需要是公共的,并且所有属性都需要是虚拟的,公共的(至少受到保护的)以及它们的setter和getter然后当DbContext将为你实例化这个实体类时,它会将它实例化为派生自的类的实例你的实体类。此类实现接口IEntityWithChangeTracker。因此,当您拥有Person实体类并且想要跟踪其中的更改时,您需要做的就是准备实现IEntityChangeTracker接口的类,如下所示:

public class PersonTracker : IEntityChangeTracker
{
    public void EntityComplexMemberChanged(string entityMemberName, object complexObject, string complexObjectMemberName)
    {
        throw new NotImplementedException();
    }

    public void EntityComplexMemberChanging(string entityMemberName, object complexObject, string complexObjectMemberName)
    {
        throw new NotImplementedException();
    }

    public void EntityMemberChanged(string entityMemberName)
    {
        throw new NotImplementedException();
    }

    public void EntityMemberChanging(string entityMemberName)
    {
        throw new NotImplementedException();
    }

    public System.Data.Entity.EntityState EntityState
    {
        get { throw new NotImplementedException(); }
    }
}

当然,您需要为这些方法提供实现。然后,您可以使用以下代码进行测试:

using (MyDbContext context = new MyDbContext("Test"))
{
    Person p = context.People.First();
    (p as IEntityWithChangeTracker).SetChangeTracker(new PersonTracker());
            //After that line EntityTracker will be called
    p.SomeProperty = "new value";
}

如果要跟踪未从db获取的新创建的实体,请不要使用new实例化它们,而是使用Create方法:

Person p = context.People.Create();

答案 1 :(得分:0)

我考虑使用IEntityWithChangeTracker接口来跟踪对实体的更改。最后,我不喜欢它能够消除上下文监控变化的能力以及添加上下文跟踪器的能力似乎失去了很多功能。

所以我最终了解了EF的Code First方法(以前是从DB First工作流程开始的)。这使我在定制实体类方面具有更大的灵活性。

所以我使用实体基类实现了INotifyPropertyChanged接口,并在每个属性的setter中触发了事件。它值得查看上面链接中的MS实现,因为它使用了一个可选的属性名称参数,因此您可以调用它而无需指定属性名称(在字符串中,yuck)。

您还可以使用字符串覆盖属性名称,以防更新一个属性会影响另一个属性的值(例如,更新FirstName会更改readonly属性FullName)。有关详细信息,请参阅here

Public MustInherit Class EntityBase
    Implements INotifyPropertyChanged

    Protected Sub NotifyPropertyChanged(<CallerMemberName()> Optional ByVal propertyName As String = Nothing)
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
    End Sub
    Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) _
        Implements INotifyPropertyChanged.PropertyChanged

End Class