比较两个集合的差异

编程中,经常需要比较两个集合以找出它们之间的差异,比如哪些元素被添加了,哪些被删除了,以及哪些被更新了。幸运的是,LINQ提供了强大的查询功能,使得这一任务变得相对简单。本文将介绍一种通用的结构实现,以便轻松地完成这项工作,并提供示例代码来演示其用法。

LINQ(Language Integrated Query)是.NET框架中一个强大的查询功能,它允许开发者以声明式的方式处理数据集合。通过LINQ,可以轻松地找出两个集合之间的差异。本文将提供一个简单的示例,展示如何实现这一功能。

使用代码

假设有两个IEnumerable集合,其中T是一个Person实体。首先,需要定义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<Person> l1 = new List<Person>(); 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<Person> l2 = new List<Person>(); l2.Add(new Person() { Id = 1, FirstName = "david", LastName = "zenou", Age = 35 });

在这个例子中,如果比较l1和l2,可以发现有一个被删除的行(Id = 2)。

List<Person> l1 = new List<Person>(); l1.Add(new Person() { Id = 1, FirstName = "david", LastName = "zenou", Age = 35 }); List<Person> l2 = new List<Person>(); 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<Person> l1 = new List<Person>(); l1.Add(new Person() { Id = 1, FirstName = "david", LastName = "zenou", Age = 35 }); List<Person> l2 = new List<Person>(); l2.Add(new Person() { Id = 1, FirstName = "david1", LastName = "zenou", Age = 36 });

在这个例子中,虽然Id相同,但是FirstName和Age不同,所以可以说这一行被更新了。

如何使用类扩展

要使用类扩展,需要提供四个参数:第一个参数是比较的源集合,第二个参数是比较的目标集合,第三个参数是一个实体比较器(IEqualityComparer comparerEntity),第四个参数是一个实体主键比较器(IEqualityComparer comparerKeyEntity)。

public class PersonEntityComparer : IEqualityComparer<Person> { 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; } } public class PersonEntityPrimaryKeyComparer : IEqualityComparer<Person> { 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. 创建PersonEntityComparer实例 PersonEntityComparer entityComparer = new PersonEntityComparer(); // 2. 创建PersonEntityPrimaryKeyComparer实例 PersonEntityPrimaryKeyComparer primarykeyComparer = new PersonEntityPrimaryKeyComparer(); // 3. 创建两个已填充或空的集合 List<Person> l1 = new List<Person>(); l1.Add(new Person() { Id = 1, FirstName = "david", LastName = "zenou", Age = 35 }); List<Person> l2 = new List<Person>(); l2.Add(new Person() { Id = 1, FirstName = "david", LastName = "zenou", Age = 35 }); l2.Add(new Person() { Id = 2, FirstName = "nathan", LastName = "zenou", Age = 3 }); // 4. 调用比较扩展 CompareResult<Person> compareResult = l1.Compare(l2, entityComparer, primarykeyComparer); // 在compareResult中,将得到三个IEnumerable集合(插入的元素、更新的元素、删除的元素) }

比较器扩展的代码

以下是ComparerResult.cs文件中的比较器扩展的代码:

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { public class CompareResult<T> { public IEnumerable<T> Inserted { get; set; } public IEnumerable<T> Updated { get; set; } public IEnumerable<T> Removed { get; set; } } public static class IEnumerableExtensions { public static CompareResult<T> Compare<T>(this IEnumerable<T> left, IEnumerable<T> right, IEqualityComparer<T> comparerEntity, IEqualityComparer<T> comparerKey) { CompareResult<T> compareResult = new CompareResult<T>(); 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; } // 相同的元素 IEnumerable<T> sameElementsRight = right.Intersect(left, comparerEntity); IEnumerable<T> sameElementsLeft = left.Intersect(right, comparerEntity); // 相同的主键元素 IEnumerable<T> sameKeyElementsRight = right.Intersect(left, comparerKey); IEnumerable<T> sameKeyElementsLeft = left.Intersect(right, comparerKey); // 更新的元素 IEnumerable<T> ElementsUpdtated = sameKeyElementsRight.Except(sameElementsRight); IEnumerable<T> elementsToUpdate = sameKeyElementsLeft.Except(sameElementsLeft); // 删除的元素 IEnumerable<T> ElementRemoved = left.Except(right, comparerEntity); ElementRemoved = ElementRemoved.Where(e => !elementsToUpdate.Contains(e, comparerEntity)); // 新增的元素 IEnumerable<T> elementDifferentsKeyRights = right.Except(left, comparerKey); IEnumerable<T> ElementAdded = right.Except(left, comparerEntity); ElementAdded = ElementAdded.Where(e => elementDifferentsKeyRights.Contains(e, comparerEntity)); compareResult.Inserted = ElementAdded; compareResult.Updated = ElementsUpdtated; compareResult.Removed = ElementRemoved; return compareResult; } } }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485