65.9K
CodeProject 正在变化。 阅读更多。
Home

实体列表<T> 数据比较器(插入、删除、更新的项目)

starIconstarIconstarIconstarIconstarIcon

5.00/5 (3投票s)

2016年8月2日

CPOL

2分钟阅读

viewsIcon

11914

downloadIcon

142

工具集合比较器。

引言

在比较实体集合时,你经常需要比较一些集合。当你比较 2 个集合时,你需要知道哪些元素被添加,哪些元素被删除,以及哪些元素被更新。

背景

通常,Linq 的强大功能允许你使用一些简单的查询来找到这些差异。今天,我尝试想象一个通用的结构实现,它允许你足够容易地做到这一点。我给你一个简单的例子来使用它,以及实现。

使用代码

想象一下,你有 2 个 IEnumerable集合,在我的例子中,T 是一个 Person 实体

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

所以,第一种情况,你可以有

List l1 = new List();
l1.Add(new Person(){ Id=1 , FirstName="david" , LastName="zenou" , Age=35});
l1.Add(new Person(){ Id=2 , FirstName="nathan" , LastName="zenou" , Age=3});

List l2 = new List();
l2.Add(new Person(){ Id=1 , FirstName="david" , LastName="zenou" , Age=35});

这里,如果我们比较 l1 和 l2,我们可以说有一个行被删除(Id = 2)。(易于检测)。

第二种情况,你可以有

List l1 = new List();
l1.Add(new Person(){ Id=1 , FirstName="david" , LastName="zenou" , Age=35});

List l2 = new List();
l2.Add(new Person(){ Id=1 , FirstName="david" , LastName="zenou" , Age=35});
l2.Add(new Person(){ Id=2 , FirstName="nathan" , LastName="zenou" , Age=3});

这里,如果我们比较 l1 和 l2,我们可以说有一个行被添加(Id = 2)。(易于检测)

最后一种情况

List l1 = new List();
l1.Add(new Person(){ Id=1 , FirstName="david" , LastName="zenou" , Age=35});

List l2 = new List();
l2.Add(new Person(){ Id=1 , FirstName="david1" , LastName="zenou" , Age=36});

在这个例子中,Id 相同,但 FirstName 和 Age 不同,所以现在我们说该行已被更新。(我们首先检查集合的主键,看到它们相等,然后检查该行的其他属性,并看到差异)

所以要使用我的类扩展,你需要提供 4 个参数:参数 1:比较 From 集合 参数 2:比较 To 集合 参数 3:一个实体比较器 (IEqualityComparercomparerEntity)。对于这个例子,我们需要实现实体比较器 IEqualityComparer

   public class PersonEntityComparer : IEqualityComparer
    {
        public bool Equals(Person x, Person y)
        {
            return (x.Id == y.Id) && 
                    x.FirstName.Equals(y.FirstName) && 
                    x.LastName.Equals(y.LastName) && 
                    x.Age == y.Age;
        }

        public int GetHashCode(Person obj)
        {
            return obj.Id;
        }
    }

参数 4:一个实体主键比较器 (IEqualityComparer comparerKeyEntity)

public class PersonEntityPrimaryKeyComparer : IEqualityComparer
    {
        public bool Equals(Person x, Person y)
        {
            return (x.Id == y.Id);
        }

        public int GetHashCode(Person obj)
        {
            return obj.Id;
        }
    }

如何利用扩展方法?在你的程序中,你必须这样做

 static void Main(string[] args)
     {
		//1- create one instance of PersonEntityComparer
		PersonEntityComparer entityComparer = new PersonEntityComparer();
		//2- create one instance of PersonEntityPrimaryKeyComparer
		PersonEntityPrimaryKeyComparer primarykeyComparer = new PersonEntityPrimaryKeyComparer();	
		//3- create 2 filled or empty collections
		List l1 = new List();
		l1.Add(new Person(){ Id=1 , FirstName="david" , LastName="zenou" , Age=35});

		List l2 = new List();
		l2.Add(new Person(){ Id=1 , FirstName="david" , LastName="zenou" , Age=35});
		l2.Add(new Person(){ Id=2 , FirstName="nathan" , LastName="zenou" , Age=3});
		
		//1-call my compare extention
		 CompareResult compareResult = l1.Compare(l2, entityComparer, primarykeyComparer);
		 
		 //Here in compareResult , you get 3 IEnumerable collecitons (inserted elements, updated elements, deleted elements)
	 }

现在查看比较器扩展 ComparerResult.cs 文件的代码

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{

    public class CompareResult
    {
        public IEnumerable Inserted { get; set; }
        public IEnumerable Updated { get; set; }
        public IEnumerable Removed { get; set; }
    }

    public static class IEnumerableExtensions
    {
        public static CompareResult Compare(this IEnumerable left, IEnumerable right, IEqualityComparer comparerEntity, IEqualityComparer comparerKey)
        {
            CompareResult compareResult = new CompareResult();

            bool isLeftEmptyOrNull = (left == null || !left.Any());
            bool isRightEmptyOrNull = (right == null || !right.Any());

            if (isLeftEmptyOrNull && isRightEmptyOrNull) return compareResult;
            else if (isLeftEmptyOrNull && !isRightEmptyOrNull)
            {
                compareResult.Inserted = right;
                return compareResult;
            }
            else if (!isLeftEmptyOrNull && isRightEmptyOrNull)
            {
                compareResult.Removed = left;
                return compareResult;
            }

            //same elements
            IEnumerable sameElementsRight = right.Intersect(left, comparerEntity);
            IEnumerable sameElementsLeft = left.Intersect(right, comparerEntity);

            Console.WriteLine("===================== Equals elements : ===========================");
            foreach (T t in sameElementsRight)
                Console.WriteLine(t);


            IEnumerable sameKeyElementsRight = right.Intersect(left, comparerKey);
            IEnumerable sameKeyElementsLeft = left.Intersect(right, comparerKey);

            IEnumerable ElementsUpdtated = sameKeyElementsRight.Except(sameElementsRight);
            IEnumerable elementsToUpdtate = sameKeyElementsLeft.Except(sameElementsLeft);

            Console.WriteLine("===================== Updated Elements : ===========================");
            foreach (T t in ElementsUpdtated)
                Console.WriteLine(t);


            IEnumerable ElementRemoved = left.Except(right, comparerEntity);
            ElementRemoved = ElementRemoved.Where(e => !elementsToUpdtate.Contains(e, comparerEntity));

            Console.WriteLine("===================== Deleted Elements : ===========================");
            foreach (T t in ElementRemoved)
                Console.WriteLine(t);


            IEnumerable elementDifferentsKeyRights = right.Except(left, comparerKey);

            IEnumerable ElementAdded = right.Except(left, comparerEntity);
            ElementAdded = ElementAdded.Where(e => elementDifferentsKeyRights.Contains(e, comparerEntity));

            Console.WriteLine("===================== Added Elements : ===========================");
            foreach (T t in ElementAdded)
                Console.WriteLine(t);

            compareResult.Inserted = ElementAdded;
            compareResult.Updated = ElementsUpdtated;
            compareResult.Removed = ElementRemoved;
            return compareResult;
        }
    }

}
 

关注点

找到一个通用的解决方案来比较任何实体列表

历史

在此处保持您所做的任何更改或改进的实时更新。

© . All rights reserved.