2

I am fetching data from database in an object and updating the same object with new values. Now I want to check which properties the same object are updated. How to check it?

I tried using creating a new object and passing the old object in new one. But after updating the old one, I found the new one has the same value.

The sample code is as below :

public class Patient
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

protected void Page_Load(object sender, EventArgs e)
{
    Patient p = new Patient();
    p.Id = 1;
    p.FirstName = "k";
    p.LastName = "p";

    Patient copy = new Patient();
    copy = (Patient)p; 

    p.FirstName = "d";
    p.LastName = "g";
    p.Id = 2;

    foreach (PropertyInfo pr in p.GetType().GetProperties())
    {
        string result = string.Empty; 

        string currentValue = copy.GetType().GetProperties().Single(o => o.Name == pr.Name).GetValue(copy, null).ToString(); 
        string pastValue = pr.GetValue(p, null).ToString();

        if (currentValue == pastValue)
        { 
            result = "equal" ; // I found that the values of properties of both objects are always same
        }
        else 
        {
            result = "different"; // I want this result
        }
    }
}

Please let me know how can I compare old object property value with new one?

Ondrej Janacek
  • 12,486
  • 14
  • 59
  • 93
Dev
  • 6,570
  • 10
  • 66
  • 112

2 Answers2

0

First of all this:

copy = (Patient)p; 

Will not make any clone, you just reassign same value to another variable (because Patient is a class, not a value type). It's equivalent to write:

Patient copy = p;

Do you see it?

Your example may work (even if I wouldn't use ToString() for comparison of "generic" properties), what's wrong is they way you do your test: copy (after incriminated line) is an alias for p so:

p.FirstName = "d";

Will change value of the same object (no matters if you access it via p.FirstName or copy.FirstName).

You have many options, for example you may implement your Clone method:

public class Patient
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public Patient Clone()
    {
        return new Patient 
        {
            Id = this.Id,
            FirstName = this.FirstName,
            LastName = this.LastName
        };
    }
}

Now change this:

Patient copy = new Patient();
copy = (Patient)p; 

To this:

Patient copy = p.Clone();

There are many options if you do not want to implement Clone() method by yourself. Most simple one that come to my mind is using some form of serialization:

public Patient Clone()
{
    using (var stream = new MemoryStream())
    {
        var formatter = new BinaryFormatter();
        formatter.Serialize(stream, this);
        stream.Seek(0, SeekOrigin.Begin);

        return formatter.Deserialize(stream);
    }
}

About comparison I would change your code a little bit (if you want to keep a reflection based comparison) to avoid comparison of properties through ToString(), you can simply use Object.Equals() because string conversion may involve many things (like localization) and it doesn't work for not primitive/simple types.

IMO it's much better to override Equals() and to implement IEquatable<Patient> (little bit more code to write but you won't rely on Reflection, how will you handle nested objects?).

Adriano Repetti
  • 65,416
  • 20
  • 137
  • 208
  • I don't want to clone it. I just want to compare values of properties for both of the objects. How to do so? – Dev Dec 02 '13 at 13:23
  • @Dev first you have to define what you want to compare! In your example you're comparing the same object with itself. In your example comparison through reflection may work (well even if I wouldn't compare through ToString) but what's wrong is what you're comparing. – Adriano Repetti Dec 02 '13 at 13:24
  • Look, I have created an object of class Patient with Id=1.. And now I am updating the id with value 2. So, I want to compare the value of property Id i.e. before update and after update. – Dev Dec 02 '13 at 13:25
  • @Dev please re-read very first lines of my answer!!! p and copy are exactly the same object! You didn't create a new one, you compare p with p and it's always exactly the same... – Adriano Repetti Dec 02 '13 at 13:27
  • I accept I can be wrong.. Then how can I reach my goal? Any other way? I want to compare the properties and make some operations if the value of property is changed. – Dev Dec 02 '13 at 13:28
  • @Dev then keep your code as is but change what you're trying to do to create your cloned object. It's not optimal but it'll work. – Adriano Repetti Dec 02 '13 at 13:34
0

So this isn't going to be an automated thing. You'll need to save the state before allowing updates to it. Consider the following class:

public class AClass
{
    private Dictionary<string, object> _originalVals =
        new Dictionary<string, object>();

    private string _aProperty;
    public string AProperty
    {
        get { return _aProperty; }
        set
        {
            SetModifiedProperty("AProperty", _aProperty);
            _aProperty = value;
        }
    }

    private void SetModifiedProperty(string propertyName, object val)
    {
        if (_originalVals.ContainsKey(propertyName)) { return; }
        _originalVals.Add(propertyName, val);
    }
}

then when you want the differences, return that Dictionary to the consumer.

Mike Perrenoud
  • 66,820
  • 29
  • 157
  • 232