一. 排序(orderby )

1. 说明

   用于对查询出来的语句进行排序,orderby 默认是升序的;降序则用  orderby xxx descending。如果是多条件排序,则在orderby后面写多个排序条件,用 逗号 隔开,如果哪个字段是要降序排列,则在它后面加descending。

2. 案例

(1).单条件升序和降序

例如:获取所有产品信息,并按照单价升序(降序)。

升序
var q = from p in db.Products
            orderby p.unitPirce
            select p;
降序
var q = from p in db.Products
            orderby p.unitPirce descending
            select p;

(2).多条件复合排序

例如:获取顾客信息,并依次按照城市名、顾客名进行升序排序。

var q = from c in db.Customers
        orderby c.City,c.Name
        select c;

例如:获取顾客信息,并依次按照城市名降序、顾客名升序排序。

var q = from c in db.Customers
        orderby c.City descending, c.Name
        select c;

例如:获取每一类产品中单价最高的产品信息,将产品按照类别ID进行升序排列。

var q = from p in db.Procucts
            group p by p.KindId into g
            orderby g.Key
            select new {
                    g.Key,
                    HighestProducts=
                            from p2 in g
                            where p2.unitPrice == g.Max(m=>m.unitPrice)
                            select p2
            };

 

二. 分组(group by)

 1. 说明-基本用法

   主要是用来对数据进行归类,可以按照类别进行输出,或者统计某个类别下的数量、最大值、最小值. 下面以一个简单的例子来说明。

例如:将产品按照类别编号进行分类,并输出。

var q = from p in db.Products
            group p by p.CategoryID into g
            select g;

分析:from p in db.Products 表示从表中将产品对象取出来。group p by p.CategoryID into g 表示对p按CategoryID字段归类。 其中g.Key就是CategoryID,g代表以CategoryID为索引的多个集合,如下图:

第十一节:Linq用法大全(二)

另外,其结果命名为g,一旦重新命名,p的作用域就结束了,所以,最后select时,只能select g。当然,也不必重新命名可以这样写:

//不推荐
var q =
    from p in db.Products
    group p by p.CategoryID;

如何对上述结果进行遍历呢?

var data = q.toList();  //这里不用延迟加载
foreach (var gp in data)
{
    //1.输出分类依据
   Console.WriteLine("类别编号为:{0}", gp.Key);   
    //2. 再次遍历输出类别下的内容
   foreach (var item in gp)
   {
      //do something
      Console.WriteLine($"产品名称:{item.pName},产品价格:{item.unitPrice}");
   }
}

同样是上面的例子,也可以这样输出匿名类。

var q =
    from p in db.Products
    group p by p.CategoryID into g
    select new { CategoryID = g.Key, g }; 

分析:在这句LINQ语句中,有2个property:CategoryID和g。这个匿名类,其实质是对返回结果集重新进行了包装。把g的property封装成一个完整的分组。如下图所示:

 第十一节:Linq用法大全(二)

 如何遍历呢?

var data = q.toList();  //这里不用延迟加载
foreach (var gp in data)
{
    //1.输出分类依据(这里 gp.CategoryID 等价于 gp.g.Key)
   Console.WriteLine("类别编号为:{0}", gp.CategoryID);   
    //2. 再次遍历输出类别下的内容
   foreach (var item in gp.g)
   {
      //do something
      Console.WriteLine($"产品名称:{item.pName},产品价格:{item.unitPrice}");
   }
}

2.  多列分组

例如:按产品的分类,又按供应商分类进行分组,并输出产品信息。

var categories =
    from p in db.Products
    group p by new
    {
        p.CategoryID,
        p.SupplierID
    }
     into g
     select new
     {
        g.Key,
        g
     };

分析:既按产品的分类,又按供应商分类。在by后面,new出来一个匿名类。这里,Key其实质是一个类的对象,Key包含两个Property:CategoryID、SupplierID。用g.Key.CategoryID可以遍历CategoryID的值。

补充一下多列分组的结果:

CategorID   SupplierID

c01    s01

c01    s02

c01    s02

c02    s02

c02    s01

c02    s01

将会分为四组

(1). c01-s01: 1个产品

(2). c01-s02: 2个产品

(3). c02-s01: 2个产品

(4). c02-s02: 1个产品

3. 表达式分组

例如:将产品分为两类,单价大于10的一类,单价小于10的一类。

var categories =
    from p in db.Products
    group p by new { Criterion = p.UnitPrice > 10 } into g
    select g;

4. 其它场景(分组求最大值,最小值、平均值、计数、求和等)

//1.按照分类ID进行分组,并且求出每组中单价的最大值
var q =
    from p in db.Products
    group p by p.CategoryID into g
    select new {
        g.Key,
        MaxPrice = g.Max(p => p.UnitPrice)
    };
//2.按照分类ID进行分组,并且求出每组中单价的最小值
var q =
    from p in db.Products
    group p by p.CategoryID into g
    select new {
        g.Key,
        MinPrice = g.Min(p => p.UnitPrice)
    };
//3.按照分类ID进行分组,并且求出每组中单价的平均值
var q =
    from p in db.Products
    group p by p.CategoryID into g
    select new {
        g.Key,
        AveragePrice = g.Average(p => p.UnitPrice)
    };
//4. 求每组的单价总和
var q =
    from p in db.Products
    group p by p.CategoryID into g
    select new {
        g.Key,
        TotalPrice = g.Sum(p => p.UnitPrice)
    };
//5. 求每组的产品个数
var q =
    from p in db.Products
    group p by p.CategoryID into g
    select new {
        g.Key,
        NumProducts = g.Count()
    };

特别注意:

  以上关于group by的代码在传统的EF调用,和EFCore 2.2版本都也可以使用,但是在EFCore3.0 3.1中都不能使用了,报错。通过查源码GitHub,确实也存在这个问题,下面给出几种临时的解决方案:

https://github.com/dotnet/efcore/issues/19894

https://github.com/dotnet/efcore/issues/19663

https://github.com/dotnet/efcore/issues?utf8=%E2%9C%93&q=groupby

临时解决方案1:在groupby前面加 AsEnumerable

var q2 = db.T_UserInfor.AsEnumerable().GroupBy(u => u.userSex).ToList();  //可以了

3.x版本测试(重点)

第十一节:Linq用法大全(二)
 1                     var db = new ypfContext();
 2 
 3                     //报错 (Client side GroupBy is not supported.)
 4                     //var list1 = (from p in db.T_UserInfor
 5                     //             group p by p.userSex into g
 6                     //             select g).ToList();
 7 
 8                     //报错 ((GroupByShaperExpression错误)
 9                     //var list2 = (from p in db.T_UserInfor
10                     //             group p by p.userSex into g
11                     //             select new
12                     //             {
13                     //                 myKey = g.Key,
14                     //                 g
15                     //             }).ToList();
16 
17                     //报错
18                     //var list3 = (from p in db.T_UserInfor
19                     //             group p by new  { ISMore30 = p.userAge > 30 } into g
20                     //             select new
21                     //             {
22                     //                 g.Key,
23                     //                 g
24                     //             }).ToList();
25 
26 
27                     //可以
28                     //var list3 = (from p in db.T_UserInfor
29                     //             group p by p.userSex into g
30                     //             select new
31                     //             {
32                     //                 g.Key,
33                     //                 myCount=g.Count(),
34                     //                 myAgeMax=g.Max(p=>p.userAge),
35                     //                 myAgeMin=g.Min(p=>p.userAge),
36                     //                 myAgeSum=g.Sum(p=>p.userAge),
37                     //                 myAgeAvg=g.Average(p=>p.userAge)
38                     //             }).ToList();
39                     //foreach (var item in list3)
40                     //{
41                     //    Console.WriteLine($"Key:{item.Key},myCount:{item.myCount},myAgeMax:{item.myAgeMax},myAgeMin:{item.myAgeMin},myAgeSum:{item.myAgeSum},myAgeAvg:{item.myAgeAvg}");
42                     //}
43 
44 
45                     /******************************************下面是改造*****************************************************/
46 
47                     //1.可以
48                     //var list1 = (from p in db.T_UserInfor.AsEnumerable()
49                     //             group p by p.userSex into g
50                     //             select g).ToList();
51                     //foreach (var item in list1)
52                     //{
53                     //    Console.WriteLine($"分类为:{item.Key}");
54                     //    Console.WriteLine($"详情为:");
55                     //    foreach (var cItem in item)
56                     //    {
57                     //        Console.WriteLine($"{cItem.id},{cItem.userName},{cItem.userSex},{cItem.userAge}");
58                     //    }
59                     //}
60 
61                     //2.可以
62                     //var list2 = (from p in db.T_UserInfor.AsEnumerable()
63                     //             group p by p.userSex into g
64                     //             select new
65                     //             {
66                     //                 myKey = g.Key,
67                     //                 g
68                     //             }).ToList();
69                     //foreach (var item in list2)
70                     //{
71                     //    Console.WriteLine($"分类为:{item.myKey}");
72                     //    Console.WriteLine($"详情为:");
73                     //    foreach (var cItem in item.g)
74                     //    {
75                     //        Console.WriteLine($"{cItem.id},{cItem.userName},{cItem.userSex},{cItem.userAge}");
76                     //    }
77                     //}
78 
79                     //3.可以
80                     //var list3 = (from p in db.T_UserInfor.AsEnumerable()
81                     //             group p by new { ISMore30 = p.userAge > 30 } into g
82                     //             select new
83                     //             {
84                     //                 g.Key,
85                     //                 g
86                     //             }).ToList();
87                     //foreach (var item in list3)
88                     //{
89                     //    Console.WriteLine($"分类为:{item.Key}");
90                     //    Console.WriteLine($"详情为:");
91                     //    foreach (var cItem in item.g)
92                     //    {
93                     //        Console.WriteLine($"{cItem.id},{cItem.userName},{cItem.userSex},{cItem.userAge}");
94                     //    }
95                     //}
View Code

相关文章:

  • 2021-11-26
  • 2021-07-07
  • 2022-02-04
  • 2021-09-20
  • 2021-09-08
  • 2021-07-18
  • 2021-05-12
  • 2022-01-25
猜你喜欢
  • 2021-06-28
  • 2021-10-23
  • 2021-08-07
  • 2021-06-14
  • 2021-09-04
  • 2021-09-13
  • 2021-12-19
相关资源
相似解决方案