In C#, how do you construct an entity comparator? (with example code of first attempt)

.net c# comparison entity-framework performance

Question

Possible Duplicate:
What is the best way to compare two entity framework entities?

I'm interested in learning the best effective method for comparing two identical items.

One entity is manually produced from an xml file (i.e., a new instance is created, and attributes are manually configured), while the other is retrieved from my object context.

If the property values differ across instances, please let me know.

My first ideas are to create hashes of each object's property values and compare them, but there could be another approach or a built-in method?

Any recommendations are appreciated.

Thank you,

James

UPDATE

I thought of this:

static class ObjectComparator<T>
{
    static bool CompareProperties(T newObject, T oldObject)
    {
        if (newObject.GetType().GetProperties().Length != oldObject.GetType().GetProperties().Length)
        {
            return false;
        }
        else
        {
            var oldProperties = oldObject.GetType().GetProperties();

            foreach (PropertyInfo newProperty in newObject.GetType().GetProperties())
            {
                try
                {
                    PropertyInfo oldProperty = oldProperties.Single<PropertyInfo>(pi => pi.Name == newProperty.Name);

                    if (newProperty.GetValue(newObject, null) != oldProperty.GetValue(oldObject, null))
                    {
                        return false;
                    }
                }
                catch
                {
                    return false;
                }
            }

            return true;
        }
    }
}

It is more of food for thought to inspire other ideas from the group; I haven't tried it yet.

Comparing attributes that contain entity values themselves might be problematic since it will never be true if the default comparator compares on object reference. Overloading the equality operator on my entities such that it compares on entity ID would be a solution.

1
4
5/23/2017 11:55:42 AM

Accepted Answer

The code won't perform as intended if left as is.

Try this easy exercise:


class A {
    public int Id { get; set; }
    public string Name { get; set; }
}

class B : A {
    public DateTime BirthDate { get; set; }
}

class ObjectComparer {
    public static void Show() {
        A a = new A();
        B b = new B();
        A a1 = new A();

        Console.WriteLine(ObjectComparator.CompareProperties(a, b));
        Console.WriteLine(ObjectComparator.CompareProperties(b, a));
        Console.WriteLine(ObjectComparator.CompareProperties(a, a1));
    }
}

You would expect it to do so.

false

false

true

but it comes back

false

false

false

Try redesigning the inner if to resemble:


if (!object.Equals(newProperty.GetValue(newObject, null), oldProperty.GetValue(oldObject, null))) { 
       return false; 
} 

By confirming this at the start of the procedure, you may also save some time if a and a1 both reference the same object.


static class ObjectComparator { 
    public static bool CompareProperties(T newObject, T oldObject) {
        if (object.Equals(newObject, oldObject)) {
            return true;
        }
        if (newObject.GetType().GetProperties().Length != oldObject.GetType().GetProperties().Length) { 
            return false; 
        } 
        else { 
            var oldProperties = oldObject.GetType().GetProperties(); 
            foreach (PropertyInfo newProperty in newObject.GetType().GetProperties()) { 
                try { 
                    PropertyInfo oldProperty = oldProperties.Single(pi => pi.Name == newProperty.Name); 
                    if (!object.Equals(newProperty.GetValue(newObject, null), oldProperty.GetValue(oldObject, null))) { 
                        return false; 
                    } 
                } 
                catch { 
                    return false; 
                } 
            } 
            return true; 
        } 
    } 
}

If speed is a concern, you may cache Type.GetProperties' return into a local variable for the duration of the procedure since Reflection does not do so on its own, at least not as of version 3.5 SP1. You will reduce the number of GetProperties calls from four to two by doing so.

You may further minimize the number of calls to GetProperties to one if you only want to compare objects that have the exact same type (or, to put it another way, do not compare between base and derived instances).

Hope this was useful.

5
8/8/2009 8:04:02 PM

Popular Answer

I would act in a same manner.

static class ObjectComparator<T>
{
    public static bool CompareProperties(T newObject, T oldObject)
    {
        if (Equals(newObject, oldObject))
        {
            return true;
        }
        PropertyInfo[] newProps = newObject.GetType().GetProperties();
        PropertyInfo[] oldProps = oldObject.GetType().GetProperties();

        if (newProps.Length != oldProps.Length)
        {
            return false;
        }

        foreach (PropertyInfo newProperty in newProps)
        {
            PropertyInfo oldProperty = oldProps.SingleOrDefault(pi => pi.Name == newProperty.Name);
            if (oldProperty == null)
                return false;

            object newval = newProperty.GetValue(newObject, null);
            object oldval = oldProperty.GetValue(oldObject, null);

            if (!Equals(newval, oldval))
                return false;
        }
        return true;
    }
}


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow