0

I have two lists I would like to compare them for updated/modified columns. Compare 2 Lists of the same class and show the different values in a new list I would like to do this using linq. The only problem is I am dealing with a lot of columns, over excess of 30 columns in each. Any suggestions would be of great help...

        //In Dal
        List<PartnerAndPartnerPositionEntity> GetAllPartnerAndPartnerPositionOldDB(int modelId);
        List<PartnerAndPartnerPositionEntity> GetAllPartnerAndPartnerPosition(int modelId);
        //BL
        //get from new db
        var list1= _partnerDAL.GetAllPartnerAndPartnerPosition(modelId);
        //get from old db
        var list2= _partnerDAL.GetAllPartnerAndPartnerPositionOldDB(modelId);
leppie
  • 115,091
  • 17
  • 196
  • 297
gaganHR
  • 337
  • 2
  • 7
  • 19

3 Answers3

1

Let's assume that:

  1. PartnerAndPartnerPositionEntity class contains a property named Id that represents the unique key of an item

Given the above you can:

Get all properties of your type

var properties = typeof(PartnerAndPartnerPositionEntity).GetProperties();

Join the two lists on the Id property and iterate through the properties to see which one has changed:

var list = list1.Join(list2,
        x => x.Id,
        y => y.Id,
        (x, y) => Tuple.Create(x, y))
    .ToList();

list.Foreach(tuple =>
{
    foreach(var propertyInfo in properties)
    {
        var value1 = propertyInfo.GetValue(tuple.Item1, null);
        var value2 = propertyInfo.GetValue(tuple.Item2, null);
        if(value1 != value2)
            Console.WriteLine("Item with id {0} has different values for property {1}.",
                tuple.Item1,Id, propertyInfo.Name);
    }
});
RePierre
  • 9,358
  • 2
  • 20
  • 37
  • Hey thanks for your snippet, But one clarification is that your snippet just checks if there is a change, I need to create a whole new row with old and new data back as a list, anyway how I could achieve that, Thanks. – gaganHR Sep 06 '13 at 08:09
  • @gaganHR, can you please be more explicit? What do you mean by "create a whole new row with old and new data back as a list"? – RePierre Sep 09 '13 at 06:13
  • I have conflicting values, that is no primary key, so the tuple does not order items in item1 when comparing values in item2, is there a way around this. – gaganHR Sep 10 '13 at 15:42
  • @gaganHR, the `Tuple` is just a pair of items of type `PartnerAndPartnerPositionEntity` so that you can compare the values of each property between those items. Why do you need ordering? – RePierre Sep 12 '13 at 07:50
  • Great got that, I had to order each lists on start date before creating a tuple of lists... Thanks... Great help indeed. – gaganHR Sep 12 '13 at 13:03
0

Well, if you want to avoid doing it the boring and tedious way, you need to use reflection to dynamically get the class members then get their values for each instance. See C# Reflection - Get field values from a simple class for the code.

Community
  • 1
  • 1
Tarik
  • 10,810
  • 2
  • 26
  • 40
  • That depends, if he's using some kind of off the shelf ORM then the members will be stored in a backing dictionary of some kind that you can just iterate keys on - the properties will just be wrappers around that – Rhys Bevilaqua Sep 06 '13 at 07:13
  • Gah...thats no fun! At DevWeek one year I watched as a developer showed us how to emit IL at runtime to compare to objects. Way faster than Reflection. – Aron Sep 06 '13 at 07:15
  • @Aron Performance is not the issue at hand. The developer wants to avoid hand coding each and every column. Resorting to IL is the equivalent of generating machine code dynamically. Unless there is a necessity, you better stick to a high level language. – Tarik Sep 06 '13 at 07:23
0

There...this will generate new IL!

public static class EqualityHelper
{
    private ConcurrentDictionary<Type, object> _cache = new ConcurrentDictionary<Type, object>();
    public bool AreEqual<T>(T left, T right)
    {
        var equality = (Func<T,T,bool>)_cache.GetOrAdd(typeof(T), CreateEquality<T>());
        return equality(left, right);
    }

    private Func<T, T, bool> CreateEquality<T>()
    {
        var left = Expression.Parameter(typeof(T));
        var right = Expression.Parameter(typeof(T));
        var properties = from x in typeof(T).GetProperties()
                        where x.GetIndexParameters().Any() == false
                        select x;
        var expressions = from p in properties
                        select Expression.Equal(
                            Expression.Property(left, p),
                            Expression.Property(right, p));
        var body = expressions.Aggregate(Expression.AndAlso);
        var lambda = Expression.Lambda<Func<T,T,bool>>(body, new [] {left, right});
        return lambda.Compile();
    }
}
Aron
  • 15,464
  • 3
  • 31
  • 64