Mysql 当实体状态更改时获得通知

Mysql 当实体状态更改时获得通知,mysql,winforms,entity-framework,Mysql,Winforms,Entity Framework,我正在构建一个应用程序,它使用实体框架(版本6)来管理持久性。这对我来说是全新的,但到目前为止我对它印象深刻 我有一个问题,我似乎无法在网上找到答案,因为被无关的答案淹没了。基本上,我有一些表单,可以向用户显示实体的详细信息以供编辑。我想做的是有一个savechanges按钮,该按钮根据实体(或者更准确地说是DbEntityEntry)的状态启用和禁用 我可以从上下文中确定实体的状态,因此确定状态不是问题。当状态发生变化时,我就有麻烦了。因此,一个实体可以从数据存储中加载并显示,并且最初将处于未

我正在构建一个应用程序,它使用实体框架(版本6)来管理持久性。这对我来说是全新的,但到目前为止我对它印象深刻

我有一个问题,我似乎无法在网上找到答案,因为被无关的答案淹没了。基本上,我有一些表单,可以向用户显示实体的详细信息以供编辑。我想做的是有一个savechanges按钮,该按钮根据实体(或者更准确地说是DbEntityEntry)的状态启用和禁用

我可以从上下文中确定实体的状态,因此确定状态不是问题。当状态发生变化时,我就有麻烦了。因此,一个实体可以从数据存储中加载并显示,并且最初将处于未更改状态。一旦用户开始编辑表单数据,实体将被修改(由于数据绑定)

我应该在哪里连接以获得实体变更的通知?我应该钩住每个控件的已更改事件还是绑定源已更改事件或其他事件

详情:
实体框架6、WinForms、MySql数据存储

如果您这样实现实体类:

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();

我考虑使用IEntityWithChangeTracker接口来跟踪对实体的更改。最后,我不喜欢这样的方式,它会删除上下文监视更改的能力,并且添加上下文的跟踪器似乎会失去很多功能

因此,我最终找到了EF的代码优先方法(以前是在DB First工作流中工作的)。这使我在定制实体类时更加灵活

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

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

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
Public必须继承类EntityBase
实现INotifyPropertyChanged
受保护的子NotifyPropertyChanged(可选的ByVal propertyName为String=Nothing)
RaiseEvent PropertyChanged(Me,新PropertyChangedEventArgs(propertyName))
端接头
公共事件PropertyChanged(发送者作为对象,e作为PropertyChangedEventArgs)_
实现INotifyPropertyChanged.PropertyChanged
末级

你的意思是“用新代码实例化它们”?那么我就不同意您的看法-Create()方法也调用构造函数。但是我们可以使用new或Create()调用构造函数,这就是区别。设置更改跟踪器是否会干扰上下文所做的跟踪?也就是说,我是否可以拥有自己的跟踪,并允许上下文也进行自己的跟踪?或者设置自定义跟踪器是否会删除上下文的跟踪器?不幸的是,它似乎会删除ef跟踪器。它不会工作,但ef仍会识别您在将更改保存到db之前所做的更改。我看到的跟踪实体的另一个选项是只实现您自己的机制,比如使用inotifypropertychange。另一方面,您可以通过调用context.People.Attach(p)来恢复ef Tracker。我认为这更糟糕。查看源代码中的实现,如果尝试更改ChangeTracker,EntityObject.SetChangeTracker()会引发异常。