-5

Is it possible to know when an property is modified within the entity itself?

E.g.:

public class StudentEntity{
    public string studentId { get; set; }
    public string studentStatus { get; set; }

   public string getStatusChangeDate{
       get 
       {
        //if studentStatus change then return date
       }
    }
}
user793468
  • 4,898
  • 23
  • 81
  • 126
  • 1
    Make it a property and then add your code in the setter – Thomas Upson Apr 20 '18 at 20:26
  • @RufusL i forgot to add getters and setters – user793468 Apr 20 '18 at 20:30
  • https://learn.microsoft.com/en-us/dotnet/framework/wpf/data/how-to-implement-property-change-notification – Rufus L Apr 20 '18 at 20:30
  • 1
    Well if you have a setter, and the `value` does not equal the current property value, then you know it has changed. Are you asking how to create a property changed event? Or do you just want to have a second property that contains the date that a property changed? What *specifically* do you want to do if a property changes? – Rufus L Apr 20 '18 at 20:32
  • Do you need to do something internal in the class or external? Might be worth checking out the `INotifyPropertyChanged` https://learn.microsoft.com/en-us/dotnet/framework/winforms/how-to-implement-the-inotifypropertychanged-interface. Part of `System.ComponentModel` – Andez Apr 20 '18 at 20:35
  • Well, it's easy enough, but you have to do it yourself. 1) Add a StudentStatusDateChanged property to your model and to the database 2) Set the StudentStatusDateChanged property when the studentStatus changes. – stuartd Apr 20 '18 at 20:36
  • The write responsibility for this generally belongs to the DB. Why notify another property in the same class? That seems kinda useless. Setup a default value for LastModifyDate in the DB using `GETDATE()`. – P.Brian.Mackey Apr 20 '18 at 20:36
  • @stuartd how to know if studentStatus changed? – user793468 Apr 20 '18 at 20:40
  • Can the student's status change in the database from a different instance of the app/website? – Ron Beyer Apr 20 '18 at 20:41
  • @RonBeyer no, it will not – user793468 Apr 20 '18 at 20:43
  • Where are you going to store the StatusChangeDate? – NetMage Apr 20 '18 at 21:23
  • @NetMage it is just for display purposes, not storing it anywhere – user793468 Apr 20 '18 at 21:24
  • 1
    You can't display anything in programming without storing it somewhere first. Where are you going to store it? – NetMage Apr 20 '18 at 21:25

2 Answers2

2

The INotifyPropertyChanged interface is used to notify clients, typically binding clients, that a property value has changed.

For example, consider a Person object with a property called FirstName. To provide generic property-change notification, the Person type implements the INotifyPropertyChanged interface and raises a PropertyChanged event when FirstName is changed.

For change notification to occur in a binding between a bound client and a data source, your bound type should either:

Implement the INotifyPropertyChanged interface (preferred).

Provide a change event for each property of the bound type.

Rewrite your code:

public class StudentEntity : INotifyPropertyChanged
{
    private string studentIdValue;
    public string StudentId
    {
        get { return this.studentIdValue; }
        set
        {
            if(value != this.studentIdValue)
            {
                this.studentIdValue = value;
                this.OnPropertyChanged(nameof(this.StudentId));
            }
        }
    }


    private string studentStatusValue;
    public string StudentStatus
    {
        get { return this.studentStatusValue; }
        set
        {
            if(value != this.studentStatusValue)
            {
                this.studentStatusValue= value;
                this.OnPropertyChanged(nameof(this.StudentStatus));
            }
        }
    }

    public string StatusChangeDate { get; set; }

    public StudentEntity(string studentId, string studentStatus)
    {
        // Don't invoke property-setters from the ctor to avoid raising the event prematurely), instead set the backing fields directly:
        this.studentIdValue     = studentId;
        this.studentStatusValue = studentStatus;
    }


    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string name)
    {
        this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}


class Program
{
    static void Main(string[] args)
    {
        var person = new StudentEntity("101", "Accept");
        person.PropertyChanged += Person_PropertyChanged;
        person.StudentStatus = "Reject";

        Console.ReadLine();
    }


    private static void Person_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        StudentEntity studentEntity = sender as StudentEntity;
        if (e.PropertyName == "StudentStatus")
        {
            studentEntity.getStatusChangeDate = DateTime.Now.ToString();
        }
    }
}
Dai
  • 141,631
  • 28
  • 261
  • 374
Saeb Panahifar
  • 479
  • 1
  • 5
  • 11
  • .. or you could just set the date in the `StudentStatus` set method. Which would be a lot easier, and OP does not require any actual notification, just to display the value. – stuartd Apr 21 '18 at 16:10
  • It will be .... – Saeb Panahifar Apr 21 '18 at 16:34
  • @stuartd how would i set the date in the StudentStatus set method? the date should only change when the status changes. Is there a way of doing this within the entity setter for StudentStatus? – user793468 Apr 23 '18 at 14:17
  • @user793468 added a little answer to show how – stuartd Apr 23 '18 at 15:19
  • Your code is incorrect: you should not call `OnPropertyChanged` every time the property setter is invoked - that can lead to infinite-loops and issues with reentrancy. Instead, only call `OnPropertyChanged` from the setter when the new value is actually different. I'll edit your answer now for the benefit of people who blindly copy+paste from SO... – Dai Aug 26 '21 at 00:49
0

You can use a method to set the value. This means each time EF loads the record, it won't get overwritten: but of course you have to remember to call the method and not set the property directly.

public class StudentEntity {
    public string studentId { get; set; }
    public string studentStatus { get; set; }
    public DateTime studentStatusChanged { get; set; }

    public void SetStudentStatus(string status) {
        studentStatus = status; 
        studentStatusChanged = DateTime.Now;
    }
} 

Example: https://dotnetfiddle.net/kF8VZR

stuartd
  • 70,509
  • 14
  • 132
  • 163
  • I'll implement this and validate but wouldnt this update the status dates for all the records? even if the status didnt change the date would get updated – user793468 Apr 23 '18 at 15:30
  • it does update the statusdate for all the records, not just the one which changed the status, should I be validating it again existing values? – user793468 Apr 23 '18 at 16:40
  • Oh right I get you. Every time the record is loaded by EF, the `set` method is called, which overwrites the date. – stuartd Apr 23 '18 at 16:45
  • I am struggling with comparing the new value against the existing within the entity itself; seems there is no recollection of old status values once the entity is hit, any suggestions? – user793468 Apr 23 '18 at 16:47
  • How about using a method to set it? Not ideal, but it will work. Edited answer. – stuartd Apr 23 '18 at 16:51