dotnetnoob
dotnetnoob

Reputation: 11360

Is there a way of comparing all the values within 2 entities?

I'm using EF4.3 so I'm referring to entities, however it could apply to any class containing properties.

I'm trying to figure out if its possible to compare 2 entities. Each entity has properties that are assigned values for clarity let say the entity is 'Customer'.

public partial class Customer
{
    public string Name { get; set; }
    public DateTime DateOfBirth { get; set; }
    ...
    ...
}

The customer visits my website and types in some details 'TypedCustomer'. I check this against the database and if some of the data matches, I return a record from the database 'StoredCustomer'.

So at this point I've identified that its the same customer returning but I wan't to valid the rest of the data. I could check each property one by one, but there are a fair few to check. Is it possible to make this comparison at a higher level which takes into account the current values of each?

if(TypedCustomer == StoredCustomer)
{
    .... do something
} 

Upvotes: 0

Views: 1944

Answers (3)

Moo-Juice
Moo-Juice

Reputation: 38820

If you're storing these things in the database, it is logical to assume you'd also have a primary key called something like Id.

public partial class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime DateOfBirth { get; set; }
    ...
    ...
}

Then all you do is:

if(TypedCustomer.Id == StoredCustomer.Id)
{
}

UPDATE:

In my project, I have a comparer for these circumstances:

public sealed class POCOComparer<TPOCO> : IEqualityComparer<TPOCO> where TPOCO : class
{
    public bool Equals(TPOCO poco1, TPOCO poco2)
    {
        if (poco1 != null && poco2 != null)
        {
            bool areSame = true;
            foreach(var property in typeof(TPOCO).GetPublicProperties())
                {
                    object v1 = property.GetValue(poco1, null);
                    object v2 = property.GetValue(poco2, null);
                    if (!object.Equals(v1, v2))
                    {
                        areSame = false;
                        break;
                    }
                });
            return areSame;
        }
        return poco1 == poco2;
    }   // eo Equals

    public int GetHashCode(TPOCO poco)
    {
        int hash = 0;
        foreach(var property in typeof(TPOCO).GetPublicProperties())
        {
            object val = property.GetValue(poco, null);
            hash += (val == null ? 0 : val.GetHashCode());
        });
        return hash;
    }   // eo GetHashCode
}   // eo class POCOComparer

Uses an extension method:

public static partial class TypeExtensionMethods
{
    public static PropertyInfo[] GetPublicProperties(this Type self)
    {
        self.ThrowIfDefault("self");
        return self.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where((property) => property.GetIndexParameters().Length == 0 && property.CanRead && property.CanWrite).ToArray();
    }   // eo GetPublicProperties


}   // eo class TypeExtensionMethods

Upvotes: 1

Joe Enos
Joe Enos

Reputation: 40421

I don't think there's much of a purpose to checking the entire object in this scenario - they'd have to type every property in perfectly exactly as they did before, and a simple "do they match" doesn't really tell you a lot. But assuming that's what you want, I can see a few ways of doing this:

1) Just bite the bullet and compare each field. You can do this by overriding the bool Equals method, or IEquatable<T>.Equals, or just with a custom method.

2) Reflection, looping through the properties - simple if your properties are simple data fields, but more complex if you've got complex types to worry about.

foreach (var prop in typeof(Customer).GetProperties()) {
    // needs better property and value validation
    bool propertyMatches = prop.GetValue(cust1, null)
        .Equals(prop.GetValue(cust2, null));
}

3) Serialization - serialize both objects to XML or JSON, and compare the strings.

// JSON.NET
string s1 = JsonConvert.SerializeObject(cust1);
string s2 = JsonConvert.SerializeObject(cust2);
bool match = s1 == s2;

Upvotes: 0

GameAlchemist
GameAlchemist

Reputation: 19294

Most simple seems to use reflexion : get the properties and/or fields you want to compare, and loop through them to compare your two objects.
This will be done with getType(Customer).getProperties and getType(Customer).getFields, then using getValue on each field/property and comparing.
You might want to add custom informations to your fields/properties to define the ones that needs comparing. This could be done by defining a AttributeUsageAttribute, that would inherit from FlagsAttribute for instance. You'll then have to retrieve and handle those attributes in your isEqualTo method.

Upvotes: 0

Related Questions