应无所住,而生其心
排名
1
文章
860
粉丝
112
评论
163
net core webapi post传递参数
庸人 : 确实坑哈,我也是下班好了好几次,发现后台传递对象是可以的,但...
百度编辑器自定义模板
庸人 : 我建议换个编辑器,因为现在百度富文本已经停止维护了,用tinymec...
ICP备案 :渝ICP备18016597号-1
网站信息:2018-2025TNBLOG.NET
技术交流:群号656732739
联系我们:contact@tnblog.net
公网安备:50010702506256
欢迎加群交流技术

集合查询的SelectMany原理

5626人阅读 2018/10/11 17:21 总访问:5186094 评论:0 收藏:0 手机
分类: EF


自己写一下里边的原理对了解它的用法有很大的帮助,select都作用类似就是把1对多的格式处理成1对1的格式,

比如这里的把UserScoreViewModel格式处理成UserScoreViewModel2

我们要想写通用的扩展方法出来可以先写一个专门的处理UserScoreViewModel格式成UserScoreViewModel2的方法,这样做也便于我们分析和理解问题,特别是如果我们要进行授课,这种方式更能够让人理解,一步一步的深入。

其实很简单就是两个遍历就好

  1. /// <summary>
  2. /// 把List<UserScoreViewModel>转换成List<UserScoreViewModel2>格式
  3. /// </summary>
  4. public List<UserScoreViewModel2> Parse(List<UserScoreViewModel> source)
  5. {
  6.     List<UserScoreViewModel2> result = new List<UserScoreViewModel2>();
  7.     foreach (UserScoreViewModel item in source)
  8.     {
  9.         foreach (Score scoreItem in item.scoreList)
  10.         {
  11.             UserScoreViewModel2 uscore = new UserScoreViewModel2();
  12.             uscore.UserName = item.UserName;
  13.             uscore.score = scoreItem;
  14.             result.Add(uscore);
  15.         }
  16.     }
  17.     return result;
  18. }

如果要处理一下为空的情况,我们加一个为空验证即可

  1. //解析成1对1的集合
  2. List<UserScoreViewModel2> userScoreViewModel2List = new List<UserScoreViewModel2>();
  3. foreach (UserScoreViewModel item in userScoreList)
  4. {
  5.     foreach (Score score in item.scores.DefaultIfEmpty())
  6.     {
  7.         UserScoreViewModel2 userScoreViewModel2 = new UserScoreViewModel2();
  8.         userScoreViewModel2.Id = item.Id;
  9.         userScoreViewModel2.UserName = item.UserName;
  10.         userScoreViewModel2.Number = item.Number;
  11.         if (score != null)
  12.         {
  13.             userScoreViewModel2.Sub = score.Sub;
  14.             userScoreViewModel2.score = score.Score1;
  15.         }
  16.         userScoreViewModel2List.Add(userScoreViewModel2);
  17.     }
  18. }

然后我们在去写通用的:

  1. public static class IEnumberExtands
  2. {
  3.     /// <summary>
  4.     /// 自己实现MySelectMany
  5.     /// </summary>
  6.     /// <typeparam name="TSource">对应外面的集合源类型</typeparam>
  7.     /// <typeparam name="TCollection">集合里边子集合类型</typeparam>
  8.     /// <typeparam name="TResult">返回值类型</typeparam>
  9.     /// <returns></returns>
  10.     public static IEnumerable<TResult> MySelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector)
  11.     {
  12.         List<TResult> resultList = new List<TResult>();
  13.         foreach (TSource tsource in source)
  14.         {
  15.             //通过外面传递的lamdba拿到集合
  16.             IEnumerable<TCollection> sublist = collectionSelector(tsource);
  17.             foreach (TCollection item in sublist)
  18.             {
  19.                 //通过外面传递的lamdba拿到返回对象
  20.                 TResult result = resultSelector(tsource, item);
  21.                 resultList.Add(result);
  22.             }
  23.         }
  24.         return resultList;
  25.     }
  26. }

上面的方法没有处理为空的情况,如果外面写了DefaultIfEmpty()就容易报错,我们可以选择在外面去处理:

  1. List<UserScoreViewModel2> userScoreList = oaEntities.UserInfo.GroupJoin(oaEntities.Score, a => a.Id, b => b.UserId, (user, score) => new UserScoreViewModel
  2. {
  3.     Id = user.Id,
  4.     UserName = user.UserName,
  5.     Number = user.Number,
  6.     scores = score
  7. }).ToList().SelectMany(a => a.scores.DefaultIfEmpty(), (a, b) =>
  8. {
  9.     UserScoreViewModel2 ss = new UserScoreViewModel2
  10.         {
  11.             Id = a.Id,
  12.             UserName = a.UserName,
  13.             Number = a.Number
  14.         };
  15.     //为空处理
  16.     if (b != null)
  17.     {
  18.         ss.Sub = b.Sub;
  19.         ss.score = b.Score1;
  20.     }
  21.     return ss;
  22. }).ToList();

当然上面哪种方式有点麻烦,我们可以在扩展方法中去处理。我们可以使用反射创建一个默认对象处理一下这种情况,不然我们就只有在外面去处理了

  1. public static IEnumerable<TResult> MySelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector)
  2. {
  3.     List<TResult> userScoreViewModel2List = new List<TResult>();
  4.     foreach (TSource item in source)
  5.     {
  6.         foreach (TCollection score in collectionSelector(item))
  7.         {
  8.             if (score == null)
  9.             {
  10.                 //使用反射创建对象,避免为空报错,为空的时候我们就给一个默认值
  11.                 TCollection collobj = Activator.CreateInstance<TCollection>();
  12.                 TResult tresult = resultSelector(item, collobj);
  13.                 userScoreViewModel2List.Add(tresult);
  14.             }
  15.             else
  16.             {
  17.                 TResult tresult = resultSelector(item, score);
  18.                 userScoreViewModel2List.Add(tresult);
  19.             }
  20.         }
  21.     }
  22.     return userScoreViewModel2List;
  23. }



欢迎加群讨论技术,1群:677373950(满了,可以加,但通过不了),2群:656732739。有需要软件开发,或者学习软件技术的朋友可以和我联系~(Q:815170684)

评价

C委托与lamdba表达式入门以及Lamdba自己实现SelectMany

?委托:l 什么委托: 本质是方法指针l 委托的作用: 作用:进行方法传递,方法可以当作一个参数进行传递,C#里边要传递...

.NET MVC EF框架中Left Join的SelectMany原理

下列代码为实现Left join 查询数据库,如果在调用SelectMany方法之前已经ToList,返回之后就结束操作数据库了,SelectMany ...

.NET实现ORM-EF的Lambda查询一对多转一对一,即实现ListT.SelectMany()方法,并对其进行为空处理

我们借助微软官方方法参数进行修改实现命名方法为MySelectMAny: public static IEnumerable&lt;TResult&gt; MySelectMA...

文件传输原理与二进制、字节、字符理解

传输文件原理: 把文件转换成字节数组,通过字节数组传输 然后接收方在把字节数据转换成文件二进制为什么能存储文件 ...

C socket通信的实现与原理

socket通信的实现与原理 本篇文章是本人通过自己的理解进行整理的,如有疑问欢迎指出在说socket之前我们先大致了解一下进...

基于接口的Sort排序方法原理

集合提供了Sort,我们可以实现IComparer接口,来实现自定义的对象排序方法:例如:根据年龄来排序publicclassMySort:ICompa...

Windows Hook原理与实现

前 言:hello ,大家好我是小付,今天和大家来谈谈Hook,第一次听到这个的时候你是不是也有点懵呢?哈哈我也是一脸懵逼在网上...

list扩展方法ForEach原理(where,FirstOrDefault同理!)

//ForEach的原理就是使用循环 //委托使用循环 publicstaticvoidMyForEach&lt;T&gt;(thisList&lt;T&gt;item,Action&lt;T...

EF SelectMarry实现原理

前言 SelectMarry实现的原理其实就是把一对多,或者集合解析成一对一 内部核心原理就是通过两个循环解析解析方法//学生...

Vue数据驱动双向绑定原理

前 言Vue 记录一下Vue数据驱动的原理(浅谈)。双向绑定原理vue实现对数据的双向绑定,是通过对数据劫持结合发布者-订阅者...

StringBuilder提高效率的原理

1、string用加号拼接的原理图注意:方法区其实不是在堆内存里面的2、3、StringBuilder和String的区别

IoC底层核心原理-组件扫描过滤器 02

作用:如果有些东西你不确定是否有问题,且你目前也用不上,就可以不加载它例如下图,你测试业务是否可用,你就只需要加载...

IoC底层核心原理-自定义导入器自定义注册器 03

一、作用:提高bean的加载数度,将没有加载到bean里面的类通过自定义导入器可以加载到bean用法:案例、1.1、加载单个类的be...

IoC底层核心原理-bean初始化过程解析 04

一、BeanFactoryPostProcessor◆作用:定义了在bean工厂对象创建后,bean对象创建前执行的动作,用于对工厂进行创建后业务处...

AOP底层原理-动态代理JDKProxy和Cglib 02

一、动态代理——JDK ProxyJDKProxy动态代理是针对对象做代理,要求原始对象具有接口实现,并对接口方法进行增强案例、调用...