Linq SelectMany


Linq SelectMany

SelectMany

SelectMany查询语法

from 标识符1  in 可枚举的表达式1
from 标识符2  in 可枚举的表达式2

先看一个简单的例子

string[] arr = { "a b c", "x y z", "1 2 3" };
            var q1 = from a in arr
                from b in a.Split()
                select b;
// 方法语法
var q1 = arr.SelectMany(a => a.Split());
  
foreach (var item in q1)
            {
                Console.WriteLine(item);
            }
// a-b-c-x-y-z-1-2-3-

将嵌套的结构展平化

image-20220718185104508

假如使用arr.Select(a => a.Split());,会发现得到的是层次化的结果

image-20220718181945195

var q2 = from a in arr
            from b in a.Split()
            orderby a, b
            select b + " come from " + a;

image-20220718182559583

转换成方法语法

       var q2 = arr.SelectMany(a => a.Split(), (a, b) => new { a, b })
                .OrderBy(@t => @t.a)
                .ThenBy(@t => @t.b)
                .Select(@t => @t.b + " come from " + @t.a);

SelectMany CROSS JOIN

var q1 = from c in context.Customers
                from p in context.Purchases
                select c.Name +" buy "+ p.Price;
                
//SELECT (COALESCE([c].[Name], N'') + N' buy ') + CAST([p].[Price] AS nvarchar(max))
FROM [Customers] AS [c]
CROSS JOIN [Purchases] AS [p]
WHERE [c].[Id] = [p].[CustomerId]

SelectMany INNER JOIN

如果采用导航属性

 var q1 = from c in context.Customers
                from p in c.Purchases
                select c.Name +" buy "+ p.Price;
                
// SELECT (COALESCE([c].[Name], N'') + N' buy ') + CAST([p].[Price] AS nvarchar(max))
FROM [Customers] AS [c]
INNER JOIN [Purchases] AS [p] ON [c].[Id] = [p].[CustomerId]

SelectMany LEFT JOIN

使用DefaultIfEmpty

var q1 = 
				from c in context.Customers
                from p in c.Purchases.DefaultIfEmpty()
                select new { c.Name, p.Description, Price = (decimal?)p.Price };
                
// SELECT [c].[Name], [p].[Description], CAST([p].[Price] AS decimal(18,2)) AS [Price]
FROM [Customers] AS [c]
LEFT JOIN [Purchases] AS [p] ON [c].[Id] = [p].[CustomerId]

上面的写法在本地查询的时候可能会报错,当p为null时,p.Description p.Price会产生空指针错误。需要改写兼容两种场景

  var q1 =
                from c in context.Customers
                from p in c.Purchases.DefaultIfEmpty()
                select new
                {
                    c.Name,
                    Description = p == null ? "" : p.Description,
                    Price = p == null ? (double?)null : p.Price
                };
                
// SELECT [c].[Name], CASE
    WHEN [p].[Id] IS NULL THEN N''
    ELSE [p].[Description]
END AS [Description], CAST([p].[Price] AS decimal(18,2)) AS [Price]
FROM [Customers] AS [c]
LEFT JOIN [Purchases] AS [p] ON [c].[Id] = [p].[CustomerId]

现在添加 Price>60 筛选

   var q1 =
                from c in context.Customers
                from p in c.Purchases.DefaultIfEmpty()
                where p.Price > 60
                select new
                {
                    c.Name,
                    Description = p == null ? "" : p.Description,
                    Price = p == null ? (double?)null : p.Price
                };
                
// SELECT [c].[Name], CASE
    WHEN [p].[Id] IS NULL THEN N''
    ELSE [p].[Description]
END AS [Description], [p].[Price]
FROM [Customers] AS [c]
LEFT JOIN [Purchases] AS [p] ON [c].[Id] = [p].[CustomerId]
WHERE [p].[Price] > 60.0E0

image-20220718191446724

发现where是在left join之后,正确的写法应该是

 var q1 =
                from c in context.Customers
                from p in c.Purchases.Where(p => p.Price > 60).DefaultIfEmpty()
                select new
                {
                    c.Name,
                    Description = p == null ? "" : p.Description,
                    Price = p == null ? (double?)null : p.Price
                };
                
// SELECT [c].[Name], CASE
    WHEN [t].[Id] IS NULL THEN N''
    ELSE [t].[Description]
END AS [Description], [t].[Price]
FROM [Customers] AS [c]
LEFT JOIN (
    SELECT [p].[Id], [p].[CustomerId], [p].[Description], [p].[Price]
    FROM [Purchases] AS [p]
    WHERE [p].[Price] > 60.0E0
) AS [t] ON [c].[Id] = [t].[CustomerId]

image-20220718191825281

Select子查询产生的是层次化的结构,不需要进行额外的null值处理。

原创文章,作者:Maggie-Hunter,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/275235.html

(0)
上一篇 2022年7月18日 20:00
下一篇 2022年7月18日 20:04

相关推荐

发表回复

登录后才能评论