如何在属性更改时触发事件?

3

当我使用DataSet时,可能会在RowChanging、RowChanged、ColumnChanging、ColumnChanged等事件上引发事件...

如何在Entity Framework中使用实体执行相同的操作?


实体类不是数据集,你试图解决什么问题? - gandjustas
1
这是 http://stackoverflow.com/questions/3460714/entity-framework-how-to-raise-onchanging-for-any-property 的重复吗? - NateTheGreat
我已经在这里回答了你的问题,展示了如何订阅事件以及EF如何处理事件。 - Matt
2个回答

5

实体已经实现了PropertyChanged事件,因为它们实现了System.ComponentModel.INotifyPropertyChanged。如果您想捕获对实体的更改,只需订阅即可。

还要注意,实体支持以下两个部分方法,如果您想响应类内的更改,可以覆盖第二个方法,这将为您提供“RowChanging”的等效项:

protected override void OnPropertyChanged(string property) {}

protected override void OnPropertyChanging(string property) {}

谢谢,我好像在某个地方已经看到过了。但我不知道的是:如何“订阅”?我需要在哪里进行更改才能使其正常工作? 是在“Entities.edmx / Entities.Designer.cs”中吗? 我需要另一个类吗? 是在这个实例上吗?=> MyEntities db = new MyEntities();? ...感谢您的澄清。 - NIF

3
你可以采取下列方法在Entity Framework中引发属性更改时引发事件:假设你有一个Pubs数据库,它有一个名为employee的表,并具有以下表结构:

Table employee in pubs database

现在我们想要跟踪任何对属性hire_date的更改。你可以按照以下方式实现(这个例子可以很容易地在LinqPad中使用 - 你只需要定义一个EF数据源,然后你可以运行这个例子):

void Main()
{
    var test=new employee();
    test.PropertyChanged += HandleSomethingHappening;
    test.hire_date = DateTime.Now;
}

public void HandleSomethingHappening(object sender, EventArgs e)
{
    var propName=((System.ComponentModel.PropertyChangedEventArgs)e).PropertyName;
    var empObj=(employee)sender;
    if (propName=="hire_date")
    {
        Console.WriteLine(propName+" changed to: " + empObj.hire_date.Date.ToString("d"));
    }
}

如果您运行它,它将在控制台上显示:
``` 雇佣日期已更改:17.09.2015 ```
这是因为在主方法中,我们通过以下方式更改了属性:
test.hire_date = DateTime.Now;

N.B.

  • 要移除事件注册,您可以使用:
    test.PropertyChanged -= HandleSomethingHappening;
  • 此处所示,Lambda表达式也是允许的;例如,您可以使用:
    test2.PropertyChanged +=
    (c, a) => Console.WriteLine(((System.ComponentModel.PropertyChangedEventArgs)a).PropertyName + " property has changed in employee entity");
    这将处理与上面示例相同的事件。但在这种情况下,无法取消注册,因为您无法隐式地引用匿名函数
  • 您还可以使用PropertyChanging事件,在发生更改之前触发before
  • 这不仅限于Entity Framework,您可以像这篇SO文章中所示的那样在每个类中使用它。

高级提示:

如果您想更好地理解幕后发生的事情,我提供了一个简化的employee类代码(仅包括运行上面示例所需的属性和事件):

public class employee //: EntityObject
{


    #region Primitive Properties

    public global::System.DateTime hire_date
    {
        get
        {
            return _hire_date;
        }
        set
        {
            //Onhire_dateChanging(_hire_date);
            _hire_date=value;
            Onhire_dateChanged();
        }
    }
    private DateTime _hire_date;


    void Onhire_dateChanged()
    {
            var handler = this.PropertyChanged; // copy before access (to aviod race cond.)
            if (handler != null)
            {                   
                var args=new PropertyChangedEventArgs() { PropertyName="hire_date" };
                handler(this, (System.EventArgs)args);
            }
    }

    public event EventHandler PropertyChanged;

    #endregion

}


public class PropertyChangedEventArgs: System.EventArgs
{
    public string PropertyName  { get; set; }
}

您可以看到事件是如何连接的 - 它在属性的“set”方法中触发。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接