首页后端开发ASP.NET如何使用LINQ、Lambda 表达式 、委托快速比较两个集合,找出需要新增、修改、删除的对象(附代码)

如何使用LINQ、Lambda 表达式 、委托快速比较两个集合,找出需要新增、修改、删除的对象(附代码)

时间2024-01-30 23:44:03发布访客分类ASP.NET浏览446
导读:收集整理的这篇文章主要介绍了如何使用LINQ、Lambda 表达式 、委托快速比较两个集合,找出需要新增、修改、删除的对象(附代码),觉得挺不错的,现在分享给大家,也给大家做个参考。本篇文章给大家带来的内容是关于如何使用LINQ、Lambd...
收集整理的这篇文章主要介绍了如何使用LINQ、Lambda 表达式 、委托快速比较两个集合,找出需要新增、修改、删除的对象(附代码),觉得挺不错的,现在分享给大家,也给大家做个参考。本篇文章给大家带来的内容是关于如何使用LINQ、Lambda 表达式 、委托快速比较两个集合,找出需要新增、修改、删除的对象(附代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

在工作中,经常遇到需要对比两个集合的场景,如:

  1. 页面集合数据修改,需要保存到数据库

  2. 全量同步上游数据到本系统数据库

在这些场景中,需要识别出需要新增、更新、删除的数据,由于每次应用是,需要比较的对象类型不一致,因此写了个相对通用的方法。这个过程中,需要理解的有以下2个核心概念:

  1. 唯一标识比较: 如果两个对象的唯一标识相等,则认为这两个对象在业务上代表同一个东西(次要属性是否相等暂不考虑)。

  2. 实体比较:表示两个对象在业务是不是相等(唯一标识相等、次要属性相等)。

代码示例如下:

void Main(){
        // 对比源集合    VAR source = Generatestudent(1, 10000, 1000);
        // 目标集合    var target = GenerateStudent(5000, 10000, 1000);
        // 唯一标识比较    FuncStudent, Student, bool>
     keyCompartor = (s, t) =>
     s.Id == t.Id;
        // 实体相等比较    FuncStudent, Student, bool>
     entITyCompartor = (s, t) =>
     s.Id == t.Id &
    &
     s.Name.Equals(t.Name) &
    &
     s.Age == t.Age;
        // 新增前准备    FuncStudent, Student>
     insertAction = (s) =>
    {
        return new Student        {
            Id = s.Id,            Name = s.Name,            Age = s.Age,            operation = "Insert"        }
    ;
    }
    ;
        // 更新前准备    FuncStudent, Student, Student>
     updateAction = (s, t) =>
    {
            t.Name = s.Name;
            t.Age = s.Age;
            t.OPEration = "Update";
            return t;
    }
    ;
        // 删除前准备    FuncStudent, Student>
     deleteAction = (t) =>
    {
            t.Operation = "Delete";
            return t;
    }
    ;
        // 去掉相等对象    RemoveDuplicate(source, target, entityCompartor, (s1, s2) =>
     s1.Id == s2.Id, keyCompartor);
        // 需要新增的集合    var insertingStudents = GetInsertingEntities(source, target, keyCompartor, insertAction);
        // 需要更新的集合    var updatingStudents = GetUpdatingEntities(source, target, keyCompartor, entityCompartor, updateAction);
        // 需要删除的集合    var deletingStudents = GetDeletingEntities(source, target, keyCompartor, deleteAction);
        // 后续业务    // InsertStudents(insertingStudents);
        // UpdateStudents(updatingStudents);
        // DeleteStudents(deletingStudents);
}
    // 集合去重PRivate void RemoveDuplicateS, T>
    (ListS>
     source, ListT>
     target, FuncS, T, bool>
     entityCompartor,    FuncS, S, bool>
     sourceKeyCompartor, FuncS, T, bool>
 keyComportor){
        var sameEntities = source.Where(s =>
     target.Exists(t =>
     entityCompartor(s, t))).ToList();
        source.RemoveAll(s =>
     sameEntities.Exists(s2 =>
     sourceKeyCompartor(s, s2)));
        target.RemoveAll(t =>
     sameEntities.Exists(s =>
     keyComportor(s, t)));
}
    // 获取需要新增的对象集合private ListT>
     GetInsertingEntitiesS, T>
    (ListS>
     source, ListT>
     target, FuncS, T, bool>
     keyComportor,    FuncS, T>
 insertAction){
        var result = new ListT>
    ();
    foreach (var s in source)    {
            var t = target.FirstOrDefault(x =>
     keyComportor(s, x));
        if (t == null)        {
                // 目标集合中不存在,则新增            result.Add(insertAction(s));
        }
    }
        return result;
}
    // 获取需要更新的对象集合private ListT>
     GetUpdatingEntitiesS, T>
    (ListS>
     source, ListT>
     target, FuncS, T, bool>
     keyComportor,    FuncS, T, bool>
     entityCompartor, FuncS, T, T>
 updateAction){
        var result = new ListT>
    ();
    foreach (var s in source)    {
            var t = target.FirstOrDefault(x =>
     keyComportor(s, x));
            if (t != null &
    &
 !entityCompartor(s, t))        {
                // 目标集合中存在,但是次要属性不相等,则更新            result.Add(updateAction(s, t));
        }
    }
        return result;
}
    // 获取需要删除的对象集合private ListT>
     GetDeletingEntitiesS, T>
    (ListS>
     source, ListT>
     target,    FuncS, T, bool>
     keyComportor, FuncT, T>
 deleteAction){
        var result = new ListT>
    ();
    foreach (var t in target)    {
            var s = source.FirstOrDefault(x =>
     keyComportor(x, t));
        if (s == null)        {
                // 源集合中存在,目标集合中需要删除            result.Add(deleteAction(t));
        }
    }
        return result;
}
    // 随机生成测试集合private ListStudent>
 GenerateStudent(int minId, int maxId, int maxNumber){
        var r = new Random();
        var students = new ListStudent>
    ();
        for (int i = 0;
     i  maxNumber;
 i++)    {
        students.Add(new Student        {
            Id = r.Next(minId, maxId),            Name = $"name: {
r.Next(1, 10)}
",            Age = r.Next(6, 10)        }
    );
    }
        return students.GroupBy(s =>
     s.Id).Select(s =>
     s.First()).ToList();
}
public class Student{
    public int Id {
     get;
     set;
 }
    public string Name {
     get;
     set;
 }
    public int Age {
     get;
     set;
 }
    public string Operation {
     get;
     set;
 }
}
    

例子中源集合与目标集合使用了相同的对象Student,但实际使用中,两者的类型可以不一样,只要最终返回目标集合的类型就可以了。

上面是我对集合比较的一点心得,只满足了小数据量的业务情景,并没有在大数据量的情况下做过调优。在这里也算是抛砖引玉,大家要是有更好的办法,还希望不吝赐教。

以上就是如何使用LINQ、Lambda 表达式 、委托快速比较两个集合,找出需要新增、修改、删除的对象(附代码)的详细内容,更多请关注其它相关文章!

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!

LambdaLINQ

若转载请注明出处: 如何使用LINQ、Lambda 表达式 、委托快速比较两个集合,找出需要新增、修改、删除的对象(附代码)
本文地址: https://pptw.com/jishu/593196.html
最新总结C语言中关于指针等相关理解和使用事宜 原来斐波拉契数列还有这种写法,你知道吗?

游客 回复需填写必要信息