tnblog
首页
视频
资源
登录
慢慢来
排名
55
文章
5
粉丝
8
评论
4
ICP备案 :渝ICP备18016597号-1
网站信息:2018-2025TNBLOG.NET
技术交流:群号656732739
联系我们:contact@tnblog.net
公网安备:50010702506256
欢迎加群交流技术

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

8233人阅读 2021/3/25 20:29 总访问:30764 评论:1 收藏:1 手机
分类: ORM_EF

我们借助微软官方方法参数进行修改实现命名方法为MySelectMAny:

  1. public static IEnumerable<TResult> MySelectMAny<TSource, TCollection, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector);

泛型参数理解:

  1. TSource:数据源泛型
  2. TCollection:解析字段后的泛型
  3. TResult:返回值泛型

实现步骤(利用嵌套foreach()和传入委托进行循环遍历):

1.预先创建一个返回值对象集合

  1. List<TResult> listTResult = new List<TResult>();

2.利用foreach()循环遍历数据源

  1. foreach (TSource itemMany in source){}

3.利用foreach()和collectionSelector()委托嵌于上一个循环中,循环遍历需要解析的字段(即本文itemMany)

  1. foreach (TCollection itemone in collectionSelector(itemMany)){}

4.通过判断解析后获得的值,进行返回值对象的创建、赋值和是否需要添加至返回值对象集合中

  1. if(itemtwo!=null){
  2. //创建一个返回对象
  3. TResult tResult=default(TResult);
  4. //利用resultSelector()委托,将返回值赋给返回对象
  5. tResult = resultSelector(itemMany, itemone);
  6. //将返回值对象添加到返回值对象集合中
  7. listTResult.Add(tResult);
  8. }

5.最后返回对象集合

具体代码:

  1. //拓展方法创建
  2. public static class SelectManyExtands
  3. {
  4. public static IEnumerable<TResult> MySelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource,TCollection, TResult> resultSelector)
  5. {
  6. //创建一个返回值对象集合
  7. List<TResult> listTResult = new List<TResult>();
  8. //利用foreach()循环遍历数据源
  9. foreach (TSource itemMany in source)
  10. {
  11. //利用foreach()和collectionSelector()委托,循环遍历需要解析的字段
  12. foreach (TCollection itemone in collectionSelector(itemMany))
  13. {
  14. //进行判断
  15. if(itemone!=null){
  16. //创建一个返回对象
  17. TResult tResult=default(TResult);
  18. //利用resultSelector()委托,将返回值赋给返回对象
  19. tResult = resultSelector(itemMany, itemone);
  20. //将返回值对象添加到返回值对象集合中
  21. listTResult.Add(tResult);
  22. }
  23. }
  24. }
  25. return listTResult;
  26. }
  27. }

微软官方并未对该方法进行为空处理,若用户在使用官方的List.SelectMany()方法时在第一个委托解析数据时使用DefaultIfEmpty()运行时会报错,我们个人实现该方法可实现为空不报错功能,如下:

.如果解析后值为空,我们可以预先实例化一个对象,将对象空值赋于返回值对象,但是使用TCollection tCollection = new TCollection();,其会报变量类型没有new()约束的错误,若我们在拓展方法后加上whewe TCollection:new()则代码就多了限制,代码耦合度就高了,所以我们使用反射(利用类型创建对象),即:类型 类型名=Activator.CreateInstance<类型名>();,就解决了。

为空处理后完整代码:

  1. //拓展方法创建
  2. public static class SelectManyExtands
  3. {
  4. public static IEnumerable<TResult> MySelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource,TCollection, TResult> resultSelector)
  5. {
  6. //创建一个返回值对象集合
  7. List<TResult> listTResult = new List<TResult>();
  8. //利用foreach()循环遍历数据源
  9. foreach (TSource itemMany in source)
  10. {
  11. //利用foreach()和collectionSelector()委托,循环遍历需要解析的字段
  12. foreach (TCollection itemone in collectionSelector(itemMany))
  13. {
  14. //创建一个返回对象
  15. TResult tResult=default(TResult);
  16. //判断itemtwo是否为空,如果为空则预先利用反射(使用类型创建对象)创建一个对象,代替为空的itemone传入resultSelector()委托中去
  17. if(itemone==null){
  18. //利用反射,使用类型创建对象
  19. TCollection tcollection=Activator.CreateInstance<TCollection>();
  20. //利用resultSelector()委托,反射传创建的对象tcollection代替itemone传入委托,将返回值赋给返回对象
  21. tResult = resultSelector(itemMany,tcollection);
  22. }else{
  23. //利用resultSelector()委托,将返回值赋给返回对象
  24. tResult = resultSelector(itemMany, itemone);
  25. }
  26. //将返回值对象添加到返回值对象集合中
  27. listTResult.Add(tResult);
  28. }
  29. }
  30. return listTResult;
  31. }
  32. }
评价

剑轩

2021/3/26 9:45:42

nice[给力],分析得很不错!

net core 使用 EF Code First

下面这些内容很老了看这篇:https://www.tnblog.net/aojiancc2/article/details/5365 项目使用多层,把数据库访问...

cAPS.net 保存base64位格式图片

publicvoidUpload() { //取出图片对应的base64位字符 stringimgBase=Request[&quot;imgBase&quot;]; //c#里边的base6...

Quartz.net实例动态改变周期调度。misfire、Cron

Quartz:Java编写的开源的任务调度作业框架 类似Timer之类定时执行的功能,但是更强大Quartz.NET:是把Quartz转成C# NuGet...

.net Windows服务发布、安装、卸载、监听脚本。服务调试

一、脚本 为方便不用每次都去写安装卸载的脚本1.安装脚本@echooff @echo开始安装【服务】 %SystemRoot%\Microsoft.NET\Fr...

c、VB.net中全角半角转换方法

///&lt;summary&gt; ///转全角的函数(SBCcase) ///&lt;/summary&gt; ///&lt;paramname=&quot;input&quot;&gt;任意字符串...

.net mvc分部页.net core分部页

.net分部页的三种方式第一种:@Html.Partial(&quot;_分部页&quot;)第二种:@{ Html.RenderPartial(&quot;分部页&quot;);}...

C.net 配合小程序实现经过第三方服务器中转文件

某些时候,微信小程序前段上传文件的时候需要经过第三方服务器再将文件上传到客户的服务器;操作如下:1:(小程序内向中端服...

.net实现QQ邮箱发送邮件功能

1、微软已经帮我们封装好了发送邮件的类MailMessage,MailMessage类构造一些邮件信息,然后通过SmtpClient进行邮件发送。Mai...

StackExchange.Redis操作redis(net core支持)

官方git开源地址https://github.com/StackExchange/StackExchange.Redis官方文档在docs里边都是官方的文档通过nuget命令下...

windows 自带netsh进行端口映射

使用netsh 把本地任意ip的25566端口 映射到192.168.81.234的25565端口netshinterfaceportproxyaddv4tov4listenaddress=0.0....

确保.net程序始终以管理员身份运行

usingSystem; usingSystem.Collections.Generic; usingSystem.Linq; usingSystem.Text; usingSystem.Threading.Tasks; ...

ASP.net Timer细节处理

Timer的用法:1:本人称之为计时器,是asp.net官方的一种。用法即是计时所用 2:关于计时有很多中方式,本人学识有限,暂...

.net core 使用session

tip:net core 2.2后可以直接启用session了,不用在自己添加一次session依赖,本身就添加了使用nuget添加引用Microsoft.AspN...

通俗易懂什么是.net?什么是.net Framework?什么是.net core?

朋友圈@蓝羽 看到一篇文章写的太详细太通俗了,搬过来细细看完,保证你对.NET有个新的认识理解原文地址:https://www.cnblo...

asp.net core2.0 依赖注入 AddTransient与AddScoped区别

asp.net core主要提供了三种依赖注入的方式其中AddTransient与AddSingleton比较好区别AddTransient瞬时模式:每次都获取一...

asp.net主动推送百度seo

虽然可以使用百度提供的js自动推送,但是估计度娘还是希望主动推送一点。哈哈^_^,女孩子嘛大多都喜欢被动一点。publicclass...