[深入学习C#]LINQ查询表达式详解(1)——基本语法、使用扩展方法和Lambda表达式简化LINQ查询

此文章非原创,转载自诗人江湖老,原文地址

  在Git上下载源码
  在工程中我们少不了要定义类或者结构去储存数据,这些数据将被临时地储存在内存中,现在我们想要对其完成一些类似于查找、过滤等等常见的任务的时候,我们该如何去做呢?
  我们可以自己写代码去对集合中的每个对象进行遍历,检查变量的每个字段看其是否满足条件。这样的故事已经发生太多次了,微软怎么可能容忍在C#里发生如此弱智的事情呢?于是,C#的设计者决定在C#中集成查询的语法,以最大限度地减少程序员书写类似代码的情况。
  这也就是我们说的LINQ(Language Intergated Query)也就是语言集成查询,我们可以使用同样的语法访问不同的数据源。

为什么要使用LINQ?

  几乎所有的应用程序都需要对数据进行处理,大部分的程序都通过自定义的逻辑来完成这些操作。这样做的弊端之意就是,代码逻辑将会跟它处理的数据的结构紧密耦合在一起,如果数据结构发生了改变,也许将会带来海量的代码改动。
  为了解决这个问题,C#将这些处理数据的代码都抽象出来,提供给了广大开发者。这就是LINQ。
  LINQ的语法类似于关系和分层查询语言(SQL和XQuery),我们可以在不更改查询代码的情况下对数据结构进行更改。LINQ比之SQL要更加灵活,可以处理更广泛的逻辑数据结构。当然,这些数据结构都需要实现了IEnumerable或者IEnumerable< T >接口,才可以进行LINQ查询。

LINQ查询表达式语法详解

表达式基础语法

  LINQ查询表达式以from子句开始,以select或者group子句结束。在这两个子句之间可以跟零个或者多个from、let、where、join或者orderby子句。
  每个from子句都是一个生成器,该生成器将引入一个包括序列(Sequence)的元素的范围变量(range variable)。每个let子句都会引入一个范围变量,以表示通过前一个范围变量计算的值。每个where子句都是一个筛选器,用于从结果中排除项。每个join子句都将指定的源序列键与其他序列的键进行比较,以产生匹配对。每个orderby子句都会根据指定的条件对各项进行重新排序。而最后的select或者group子句根据范围变量来指定结果的表现形式。最后可以使用into子句来连接查询,将某一查询结果的视为后续查询的生成器。

标准查询操作符

  在了解LINQ查询表达式之前,怎么能不了解下它的查询操作符呢?下面列表列出了LINQ定义的标准查询操作符。

表1:LINQ标准查询操作符

标准查询操作符说明
where OfType<TResult>筛选操作符定义了返回元素的条件。在Where查询操作符中,可以使用谓词,例如Lambda表达式定义的谓词,来返回布尔值。OfType<TResult>根据类型筛选元素,只返回TResult的类型元素
Select 和SelectMany投射操作符用于把对象转换为另一个类型的新对象。Select和SelectMany定义了根据选择器函数选择结果值的投射。
OrderBy、ThenBy 、OrderByDescending 、ThenByDescending 、Reverse排序操作符改变所返回的元素的顺序。OrderBy按升序排列,OrderByDescending按降序排列。如果第一次排序结果很类似,就可以使用ThenBy和ThenByDescending操作符进行第二次排序。Reverse反转集合中的元素顺序。
GroupBy、ToLookUp组合运算符把数据放在组里面。GroupBy操作符组合有公共键的元素。ToLookUp通过创建一个一对多的字典,来组合元素。
Join、GroupJoin链接运算符用于合并不直接相关的集合。使用Join操作符,可以根绝键选择器函数连接两个集合,这类似于SQL中的Join。GroupJoin操作符连接两个集合,组合其结果。
Any、All、Contains如果元素序列满足指定的条件,两次操作符就返回布尔值。Any、ALll和Contains都是限定符操作符。Any确定集合中是否有确定满足谓词函数的元素。ALll确定集合中的所有元素是否都满足谓词函数。Contains检查某个元素是否在集合中。这些操作符都返回一个布尔值。
Take、Skip、TakeWhile、SkipWhile分区操作符返回集合的一个子集,Take、Skip、TakeWhile、SkipWhile都是分区操作符。使用它们可以得到部分结果,使用Take必须指定要从集合中提取的元素个数;Skip跳过指定个数的元素,提取其它元素;TakeWhile提取条件为真的元素。
Distinct、Union、Intersect、Except、ZipSet操作符返回一个集合。Distinct从集合中删除重复的元素,除了Distinct之外,其它的Set操作符都需要两个集合。Union返回出现在其中一个集合中的唯一元素。Intersect返回两个集合中都有的元素。Except返回值出现在一个集合中的元素。Zip是.NET 4新增的,它把两个集合合并为一个。
First、FirstOrDefault、Last、LastOrDefault、ElementAt、ElementAtOrDefault、Single、SingleOrDefault这些元素操作符仅返回一个元素。First返回第一个满足条件的元素。FirstOrDefault类似于First,单如果没有找到满足条件的元素,就返回类型的默认值。Last返回最后一个满足条件的元素。ElementAt指定了要返回的元素的位置。Single只返回一个满足条件的元素。如果有多个元素都满足条件,就抛出一个异常。
Count、Sum、Min、Max、Average、Aggregate聚合操作符计算集合的一个值。利用这些聚合操作符,可以计算所有值的总和、所有元素的个数、值最大和最小的元素,以及平均值等等。
ToArray、ToEnumerable、ToList、ToDictionary、Cast<TRsult>这些转换操作符将集合转换为数组:IEnumerable、IList、IDictionary等。
Empty、Range、Repeat这些生成操作符返回一个心机和。使用Empty时集合是空的;Range返回一系列数字;Repeat返回一个始终重复一个值的集合。

设置案例背景

  假设我们有4个类,Customer,Order,Detail,Product,它们的定义如下:

Customer类字段字段类型
CustomerIDint
Countrystring
Namestring
Citystring
OrdersList<Order>
Order类字段字段类型
OrderIDint
CustomerIDint
Totalint
OrderDateDateTime
DetailsList<Detail>
Detail类字段字段类型
DetailIDint
OrderIDint
UnitPricedouble
Quantitydouble
ProductIDint
Product类字段字段类型
ProductIDint
ProductNamestring

  假设现在它们各自有一个List集合,分别为Customers,Orders,Details,Products。我们在这基础之上来一步步阐述LINQ查询表达式。
  customers数据:

CustomerIDCityCountryNameOrders
0北京中国小米orders.FindAll(c => c.CustomerID == 0)
1首尔韩国三星orders.FindAll(c => c.CustomerID == 1)
2加州美国苹果orders.FindAll(c => c.CustomerID == 2)
3台北中国HTCorders.FindAll(c => c.CustomerID == 3)
4珠海中国魅族orders.FindAll(c => c.CustomerID == 4)
5北京中国华为orders.FindAll(c => c.CustomerID == 5)
6上海中国索尼orders.FindAll(c => c.CustomerID == 6)
7北京中国联想orders.FindAll(c => c.CustomerID == 7)
8上海中国诺基亚orders.FindAll(c => c.CustomerID == 8)

  
  orders数据:

OrderIDCustomerIDOrderDateDetails
00DateTime.Nowdetails.FindAll(d => d.OrderID == 0)
10DateTime.Nowdetails.FindAll(d => d.OrderID == 1)
21DateTime.Nowdetails.FindAll(d => d.OrderID == 2)
31DateTime.Nowdetails.FindAll(d => d.OrderID == 3)
42DateTime.Nowdetails.FindAll(d => d.OrderID == 4)
52DateTime.Nowdetails.FindAll(d => d.OrderID == 5)
63DateTime.Nowdetails.FindAll(d => d.OrderID == 6)
73DateTime.Nowdetails.FindAll(d => d.OrderID == 7)
84DateTime.Nowdetails.FindAll(d => d.OrderID == 8)
95DateTime.Nowdetails.FindAll(d => d.OrderID == 9)
106DateTime.Nowdetails.FindAll(d => d.OrderID == 10)
116DateTime.Nowdetails.FindAll(d => d.OrderID == 11)
127DateTime.Nowdetails.FindAll(d => d.OrderID == 12)
137DateTime.Nowdetails.FindAll(d => d.OrderID == 13)
148DateTime.Nowdetails.FindAll(d => d.OrderID == 14)
158DateTime.Nowdetails.FindAll(d => d.OrderID == 15)
168DateTime.Nowdetails.FindAll(d => d.OrderID == 16)

  
  details数据:

DetailIDOrderIDProductIDQuantityUnitPrice
000100010
11121348
22112369
3307547
442235412
550698513
662421310
773197710
8822876
995977812
1010485411
1111275610
1212310009
131317868
141433467
151525766
1616078210

  
  products数据:

ProductIDProductName
0samsung
1nokia
2apple
3xiaomi
4huawei
5lenovo

Demo查询表达式

条件筛选

  使用where子句,可以按照一个或者多个条件筛选集合,where子句的表达式的结果类型应该是布尔类型。
  筛选在北京且名称以‘小’开头的顾客。

var query = from c in customerswhere c.City == "北京" && c.Name.StartsWith("小")select c;
foreach (Customer item in query)
{Console.WriteLine(item.Name + "\t\t" + item.City);
}
Console.ReadKey();

  该LINQ查询会返回在北京而且名字以“小”开头的Customer集合。
  输出结果:
  这里写图片描述
  

复合from子句筛选

  当需要根绝对象的一个成员进行筛选,而该成员本身是一个集合或者列表,就可以使用复合的from子句。
  筛选订单数量大于800的信息。

var query = from c in customersfrom o in c.Ordersfrom d in o.Detailswhere d.Quantity > 800select new { Name = c.Name, Total = d.UnitPrice * d.Quantity };foreach (var item in query)
{Console.WriteLine(item.Name + "\t\t" + item.Total);
}
Console.ReadKey();

  输出结果:
  这里写图片描述
  

排序

  要对序列排序,需要使用orderby子句。
  按照城市、顾客ID进行排序。 

var query = from c in customersfrom o in c.Ordersorderby c.City, o.CustomerIDselect new { Name = c.Name, City = c.City, OrderID = o.OrderID };foreach (var item in query)
{Console.WriteLine(item.Name + "\t\t" + item.City + "\t\t" + item.OrderID);
}
Console.ReadKey();

  输出结果:
  这里写图片描述
    

分组

  要根木一个关键值对查询结果分组,可以使用group子句。
  统计各个产品的订单数量。  

var query = from d in detailsgroup d by d.ProductID into gorderby g.Count(), g.Keyselect new { Name = g.Key, Count = g.Count() };
Console.WriteLine("ProductID"+ "\t" + "Count");
foreach (var item in query)
{Console.WriteLine(item.Name + "\t\t" + item.Count);
}
Console.ReadKey();

  输出结果:
  这里写图片描述
  

对嵌套的对象分组

  如果分组的对象包含嵌套的序列,则各个改变select子句创建的匿名类型。
  统计各个产品的订单数量,并输出各个订单的订货数量。

var query = from d in detailsgroup d by d.ProductID into gorderby g.Count(), g.Keyselect new{Name = g.Key,Count = g.Count(),Quantity =  from d in gorderby d.Quantityselect d.Quantity};Console.WriteLine("ProductID"+"\t"+"Count"+"\t"+"Quantity");
foreach (var item in query)
{Console.Write(item.Name + "\t\t" + item.Count+"\t");foreach (var quantity in item.Quantity){Console.Write("{0};", quantity);}Console.WriteLine();
}
Console.ReadKey();

  输出结果:
  这里写图片描述
  

连接

  使用join子句可以根据特定的条件合并两个数据源,但之前要获得两个要连接的列表。
  统计各个顾客和其订单的信息。

var query = from r infrom c in customersfrom o in c.Ordersfrom d in o.Detailsselect new { Name = c.Name, City = c.City, Money = d.Quantity * d.UnitPrice, ProductID = d.ProductID }join t infrom p in productsselect pon r.ProductID equals t.ProductIDselect new { Name = r.Name, City = r.City, Money = r.Money, ProductName = t.ProductName };
Console.WriteLine("Name" + "\t" + "City" + "\t" + "Money" + "\t" + "ProductName");
foreach (var item in query)
{Console.WriteLine(item.Name + "\t" + item.City + "\t" + item.Money + "\t" + item.ProductName);
}
Console.ReadKey();

  输出结果:
  这里写图片描述
    

聚合操作符

  聚合操作符(包括Count()、Sum()、Min()、Max()、Average()和Aggregate())它们不返回一个序列,而是返回一个值。
  Count()方法返回集合中的项数;Sum()方法汇总序列中所有数字,返回这些数字的和;Min()方法返回集合中的最小值;Max()方法返回集合中的最大值;Average()方法计算集合中的平均值;Aggregate()方法,可以传递一个Lambda表达式,该表达式对所有的值进行聚合。
  这些方法的使用方式类似,都是直接对序列或者集合进行操作。下面用Sum()做一个示例:
  统计各个顾客总共订单的订货数量。

var query = from r infrom c in customersselect new{Name = c.Name,OrderCount = (  from o in c.Ordersfrom d in o.Detailsselect d.Quantity).Sum()}orderby r.OrderCountselect r;

  输出结果:
  这里写图片描述

使用扩展方法和Lambda表达式简化LINQ查询

什么是扩展方法

  当方法的第一个形参包含this修饰符的时候,该方法称为扩展方法。扩展方法只能在非泛型、非嵌套的静态类中声明,扩展方法的第一个形参不能带有除this之外的其他任何修饰符,而且形参类型不能是指针类型。
  下面的程序是一个扩展方法的示例:

public static class Extensions
{public static void HelloWorld(this string str){Console.WriteLine("{0} 调用了:HellWorld",str);}
}

  现在就可以调用该方法了:

string str="Jay";
str.HelloWorld();

  我们可以看到,控制台中输出了“Jay 调用了:HelloWorld”。
  之所以这样,是因为HelloWorld第一个参数类型为string类型,因此该方法就是string类型的扩展方法,所有的string类型变量都可以调用,而变量的内容就是传递给HelloWorld的参数。
  上面的程序和下面的代码结果一样:

string str = "Jay";
Extensions.HelloWorld(str);

    LINQ扩展方法

      LINQ为IEnumerable<T>接口提供了各种扩展方法,以便用户在实现了该接口的任意集合上使用LINQ查询。表1中列出的LINQ查询操作符,都有相应的扩展方法实现。
      使用扩展方法可以和使用LINQ查询表达式获得十分类似甚至是相同的结果,当扩展方法和Lambda表达式结合的时候,会大大简化LINQ查询。
      

    简化LINQ查询

      前面一节的条件筛选LINQ表达式可以简化为:

    var query = customers.Where(c => c.City == "北京" && c.Name.StartsWith("小")).Select(c => c);
    • 1

      
      前面一节的条件复合from子句筛选LINQ表达式可以简化为:

    var query = customers.SelectMany(c => c.Orders, (c, o) => new { _customer = c, _order = o, _detail = o.Details }).SelectMany(a => a._detail, (a, b) => new { _var = a, Total = b.Quantity * b.UnitPrice, Quantity = b.Quantity }).Where(_nameless => _nameless.Quantity > 800).Select(_annonymous => new { Name = _annonymous._var._customer.Name, Total = _annonymous.Total });
    • 1

      
      前面一节的排序LINQ表达式可以简化为:

    var query = customers.SelectMany(c => c.Orders, (c, o) => new { _customer = c, _order = o }).OrderBy(_var => _var._customer.City).ThenBy(_var => _var._order.CustomerID).Select(_annonymous => new { Name = _annonymous._customer.Name, City = _annonymous._customer.City, OrderID = _annonymous._order.OrderID });
    • 1

      
      前面一节的分组LINQ表达式可以简化为:

    var query = details.GroupBy(d => d.ProductID).OrderBy(g => g.Count()).ThenBy(g => g.Key).Select(g => new { Name = g.Key, Count = g.Count() });
    • 1

      
      前面一节的对嵌套的对象分组LINQ表达式可以简化为:

    var query = details.GroupBy(d => d.ProductID).OrderBy(g => g.Count()).ThenBy(g => g.Key).Select(_var => new { Name = _var.Key, Count = _var.Count(), Quantity = _var.OrderBy(d => d.Quantity).Select(d => d.Quantity) });
    • 1

      前面一节的连接LINQ表达式可以简化为:

    var query = customers.SelectMany(c => c.Orders, (c, o) => new { Name = c.Name, City = c.City, Details = o.Details }).SelectMany(_var => _var.Details, (_var, _detail) => new { Name = _var.Name, City = _var.City, Money = _detail.Quantity * _detail.UnitPrice, ProductID = _detail.ProductID }).Join(products, a => a.ProductID, b => b.ProductID, (a, b) => new { Name = a.Name, City = a.City, Money = a.Money, ProductName = b.ProductName });
    • 1

      
      前面一节的聚合操作LINQ表达式可以简化为:

    var query = customers.Select(c => new { Name = c.Name, OrderCount = c.Orders.SelectMany(o => o.Details, (o, d) => new { _Quantity = d.Quantity }).Select(_var => _var._Quantity).Sum() }).OrderBy(_var => _var.OrderCount);
    • 1

      以上利用扩展方法和Lambda表达式的简化后的LINQ查询代码的查询结果,与LINQ查询表达式结果完全一样,证明这样是完全可行的。
      唯一的问题就是代码看起来比较费解了。

    LINQ查询表达式简化转换原则

      看到这里我们可能要奇怪,为什么我们能用这样的方式来简化LINQ查询表达式呢?
      关于这个问题,我们将在下一篇文章进行详细讲解。
      欢迎大家点击阅读。
      本人还是菜鸟,写的不对的地方还请各位不吝赐教!

    本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/548653.shtml

    如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

    相关文章

    hcip第18天

    链路聚合 --- 可以将多个物理接口捆绑成一个逻辑接口&#xff0c;即将N条物理链路聚合为一条逻辑链路。可以在不升级硬件的条件下&#xff0c;达到增加带宽的效果。 我们将逻辑链路&#xff0c;称为聚合链路&#xff0c;在华为设备中称为ETH-TRUNK链路&#xff08;这个技术是针…

    x264编码参数大测试:08 subme与指定码率(1000Kbps)

    一、测试内容 测试方法—— x264编码参数大测试&#xff1a;索引贴 http://www.cnblogs.com/zyl910/archive/2011/12/14/x264_encode_param.html 测试参数—— subme&#xff1a;9、10、11。设定子像素&#xff08;subpixel&#xff09;运动估计&#xff08;motion estimation&…

    第十八天实验-交换综合

    配置思路 eth-trunk &#xff1e; 创建vlan &#xff1e; 划分vlan &#xff1e; trunk干道 &#xff1e; STP &#xff1e; SVI &#xff1e; VRRP &#xff1e; DHCP 一&#xff0c;配置eth-trunk SW&#xff11;&#xff1a; [sw1]int Eth-Trunk 0 ---创建…

    HCIA第九节课作业

    子网划分&#xff1a; 如何去合理的分配地址 总共需要多少个网段&#xff1f; 14个网段 环回接口8个6个 192.168.1.0/14 借4位 192.168.1.0/28 192.168.1.16/28 192.168.1.32/28 192.168.1.48/28 可用地址数量是多少?14个地址 子网划分第多少位的时候,只有两个可…

    如何下载防盗链的歌曲?

    初音&#xff0c;大家都很熟悉了。它是YAHAMA&#xff08;雅马哈&#xff0c;就是生产电子琴的那个公司&#xff09;推出的音乐编辑软件vocaloid的一款产品。 1月27号&#xff08;春节放假回来的前一天&#xff09;就要推出vocaloid 3啦&#xff01;&#xff01; 很喜欢IA的《鸟…

    如何发布.Net MVC 网站项目(攻略集锦)

    转载自诗人江湖老&#xff0c;原文地址 参考文献既然是攻略&#xff0c;就必然有参考文献&#xff0c;放在文章开头&#xff0c;以示敬意&#xff01; 1.MVC项目发布步骤 2.未能从程序集加载“System.ServiceModel.Activation.HttpModule” 3. Win7 IIS 另一个程序正在使用此…

    ssh建立原理 及配置两台主机的远程连接实现免密登陆

    一、SSH是什么&#xff1f;具体的实现有哪些&#xff1f; SSH是一种协议标准 SSH是用在安全远程登录以及其它安全网络服务 二、SSH原理&#xff1a; SSH为Secure Shell的缩写&#xff0c;默认端口22&#xff0c;由IETF的网络小组&#xff08;Network Working Group&…

    常用 SQL Server 规范集锦

    原文地址 常见的字段类型选择   &#xff11;.字符类型建议采用varchar/nvarchar数据类型   &#xff12;.金额货币建议采用money数据类型   &#xff13;.科学计数建议采用numeric数据类型   &#xff14;.自增长标识建议采用bigint数据类型 (数据量一大&#xff…

    Linux服务器搭建----Web服务器(apache)

    WWW的介绍 万维网&#xff08;亦作“Web”、“WWW”、“W3”&#xff0c;英文全称为“World Wide Web”&#xff09;&#xff0c;是一个由许多互相链接的超文本组成的系统&#xff0c;通过互联网访问。在这个系统中&#xff0c;每个有用的事物&#xff0c;称为一样“资源”&…

    F5 配置手册 -F5 BIG-IP 10.1-1-激活

    F5 配置手册 F5 BIG-IP 10.1-1-激活 统一沟通(中国)有限公司 2012-01-29 前言&#xff1a; F5---太贵! 不过你如果有命运看到这个文章,F5也就不值钱了。 因为:F5提供测试版的虚拟机,我们买不起,总应该玩得起吧! 但愿F5提供更多的机会,给别人机会,也是给自己机会。 参照: 你也可…

    Beginning iCloud in iOS 5 Tutorial Part 2(转载)

    原文地址&#xff1a;http://www.raywenderlich.com/6031/beginning-icloud-in-ios-5-tutorial-part-2 Setting Up the User Interface The Xcode project template we chose already set up an empty view controller for us. We will extend it by adding the current docume…

    JQuery Datatables 服务端分页简单应用学习

    背景介绍 最近在一个简单小项目中碰到需要一个前端数据表格控件&#xff0c;在看了网上的资料后最终选择了JQuery Datatables。Datatables功能及其强大&#xff0c;基本满足我的所有需求&#xff0c;在加上其插件Editor具有inline模式&#xff0c;很多需要直接修改数据的功能不…

    Java API 设计清单

    为什么80%的码农都做不了架构师&#xff1f;>>> 在设计Java API的时候总是有很多不同的规范和考量。与任何复杂的事物一样&#xff0c;这项工作往往就是在考验我们思考的缜密程度。就像飞行员起飞前的检查清单&#xff0c;这张清单将帮助软件设计者在设计Java API的…

    利用FSMT进行文件服务器迁移及整合

    当企业文件服务器&#xff08;DFS、共享文件夹等&#xff09;面临硬件更新、系统升级或文件服务器合并的情况时&#xff0c;往往会出现不确定的文件丢失、需要重新设置所有权限、无法将多个文件服务器集成到一台服务器上等问题&#xff0c;为了保证文件服务器的数据完整以及权限…

    RHEL 6上KVM的安装配置及使用-将物理接口桥接到桥接器

    作业环境服务器端操作系统&#xff1a;Red Hat Enterprise Linux Server release 6.0 (Santiago)KVM&#xff1a;qemu-kvm-0.12.1.2-2.113.el6.x86_64 客户端操作系统&#xff1a;Windows 7KVM管理工具&#xff1a;Xming 6.9 一、安装KVM及相关软件 1、KVM 需要有 CPU 的支持&a…

    C#中IEnumerableT.Distinct()将指定实体类对象用Lambda表达式实现多条件去重

    背景说明 在EF等ORM框架中需要以List实体类的方式对数据进行大量操作&#xff0c;其中免不了对一些数据进行去重复&#xff0c;而C#中IEnumerable.Distinct()便提供了这一功能。只是对刚开始接触的新人来说比价抽象难以接受&#xff0c;本文会对这一功能进行简要说明&#xff…

    C#中利用Linq.Dynamic实现简单的动态表达式构建查询

    背景介绍 在ADO.NET中我们可以根据用户输入的查询条件拼接出指定的SQL语句进行查询或者筛选出所需的数据&#xff0c;但是在ORM框架如EF中&#xff0c;我们一般用LINQ操作数据查询&#xff0c;LINQ是否可以像SQL一样拼接查询条件呢&#xff1f;答案是可以的。这一技术叫Linq.D…

    C#中IEnumerableT.GroupBy()的简单使用

    背景介绍 在实际项目中&#xff0c;对数据进行GroupBy肯定是常用需求之一&#xff0c;特别是采用EF等ORM框架后隔绝了用SQL语句直接操作数据&#xff0c;LINQ中的GroupBy肯定是要掌握的。 首先先对一个字段GroupBy&#xff0c;代码如下&#xff1a; static void Main(string[…

    25 个精美的后台管理界面模板和布局

    任何系统都会有一个管理后台&#xff0c;好看的管理后台看起来赏心悦目&#xff0c;管理的时候心情也舒畅&#xff0c;本文给大家推荐 25 个制作精美的后台管理界面的模板和布局&#xff0c;你值得拥有。 Free Admin Template Web App Theme Spring Time Free Admin Template F…

    C#中IEnumerableT.Aggregate()的简单使用

    背景介绍 IEnumerable<T>.Aggregate()在LINQ使用中好像很不起眼&#xff0c;但我个人认为这是十分实用并且强大的&#xff0c;支持自定义聚合操作&#xff0c;方法定义中的Func包含3个TSource参数&#xff0c;分别为下一个执行聚合的元素&#xff0c;当前聚合的元素&…