实体列表<T> 数据比较器(插入、删除、更新的项目)
工具集合比较器。
引言
在比较实体集合时,你经常需要比较一些集合。当你比较 2 个集合时,你需要知道哪些元素被添加,哪些元素被删除,以及哪些元素被更新。
背景
通常,Linq 的强大功能允许你使用一些简单的查询来找到这些差异。今天,我尝试想象一个通用的结构实现,它允许你足够容易地做到这一点。我给你一个简单的例子来使用它,以及实现。
使用代码
想象一下,你有 2 个 IEnumerable
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:一个实体比较器 (IEqualityComparerIEqualityComparer
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
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;
}
}
}
关注点
找到一个通用的解决方案来比较任何实体列表
历史
在此处保持您所做的任何更改或改进的实时更新。