Linq之SelectMany(from..from..复合from子句)

1、 Linq之SelectMany(from..from..复合from子句)

如果需要根据对象的一个成员进行筛选,而该成员本身一个集合,就可以使用复合的from子句

代码如下:

public class ms
{
    void Main()
    {
        List<Person> personList = new List<Person>
        {
            new Person
            {
                Name = "P1", Age = 18, Gender = "Male",
                Dogs = new Dog[]
                {
                    new Dog { Name = "D1" },
                    new Dog { Name = "D2" }
                }
            },
            new Person
            {
                Name = "P2", Age = 19, Gender = "Male",
                Dogs = new Dog[]
                {
                new Dog { Name = "D3" }
                }
            },
            new Person
            {
                Name = "P3", Age = 17,Gender = "Female",
                Dogs = new Dog[]
                {
                    new Dog { Name = "D4" },
                    new Dog { Name = "D5" },
                    new Dog { Name = "D6" }
                }
            }
        };
        Console.WriteLine("********第⼀种⽤法*************************************");
        //官⽅释义:将序列的每个元素投影到 IEnumerable<TResult> 并将结果序列合并为⼀个序列。
        //public static IEnumerable<TResult> SelectMany<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector);
        var results1 = personList.SelectMany(p => p.Dogs);
        // 其等价的LINQ语句为:
        //var results1 = from p in personList
        // from d in p.Dogs
        // select d;
        foreach (var dog in results1)
        {
            Console.WriteLine(dog.Name);
        }
        Console.WriteLine();
        Console.WriteLine("********第⼆种⽤法*************************************");
        //官⽅释义:将序列的每个元素投影到 IEnumerable<TResult>,并将结果序列合并为⼀个序列。每个源元素的索引⽤于该元素的投影表。
        //public static IEnumerable<TResult> SelectMany<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TResult>> selector);
        var results2 = personList.SelectMany((p, i) => p.Dogs.Select(d => new
        {
            Name = $"{i},{d.Name}"
        }));
        foreach (var dog in results2)
        {
            Console.WriteLine(dog.Name);
        }
        Console.WriteLine();
        Console.WriteLine("********第三种⽤法*************************************");
        //官⽅释义:将序列的每个元素投影到 IEnumerable<TCollection>,并将结果序列合并为⼀个序列,并对其中每个元素调⽤结果选择器函数。
        //public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection
        var results3 = personList.SelectMany(p => p.Dogs, (p, d) => new { PersonName = p.Name, DogName = d.Name });
        // 其等价的LINQ语句为:
        //var results3 = from p in personList
        // from d in p.Dogs
        // select new { PersonName = p.Name, DogName = d.Name };
        foreach (var result in results3)
        {
            Console.WriteLine($"{result.PersonName},{result.DogName}");
        }
        Console.WriteLine();
        Console.WriteLine("********第四种⽤法*************************************");
        //官⽅释义:将序列的每个元素投影到 IEnumerable<TCollection>,并将结果序列合并为⼀个序列,并对其中每个元素调⽤结果选择器函数。每个源元素的索引⽤于该元素的中间投影表。
        //public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(this IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection
        var results4 = personList.SelectMany((p, i) => p.Dogs.Select(d => new
        {
            Name = $"{i},{d.Name}"
        }),(p, d) => new { PersonName = p.Name, DogName = d.Name });
        foreach (var result in results4)
        {
            Console.WriteLine($"{result.PersonName},{result.DogName}");
        }
        Console.WriteLine();
    }
    class Person
    {
        public string Name { set; get; }
        public int Age { set; get; }
        public string Gender { set; get; }
        public Dog[] Dogs { set; get; }
    }
    public class Dog
    {
        public string Name { set; get; }
    }
}

结果:

********第⼀种⽤法*************************************
D1
D2
D3
D4
D5
D6
********第⼆种⽤法*************************************
0,D1
0,D2
1,D3
2,D4
2,D5
2,D6
********第三种⽤法*************************************
P1,D1
P1,D2
P2,D3
P3,D4
P3,D5
P3,D6
********第四种⽤法*************************************
P1,0,D1
P1,0,D2
P2,1,D3
P3,2,D4
P3,2,D5
P3,2,D6

 

2、复合from⼦句与join⼦句 

复合from⼦句实际上就是联接查询,⼤部分复合from⼦句(并不是所有,如cross join)的Linq完全可以⽤join⼦句的Linq来重写,两者⽣成的Sql也相同,推荐使⽤join
Linq,这种写法与Sql更接近,更易读。

var query1 = from o in dbContext.Orders
from od in o.Order_Details
select o;
var query2 = from o in dbContext.Orders
             join od in dbContext.Order_Details
             on o.OrderID equals od.OrderID
select o;

 

posted @ 2022-05-11 11:14  幽冥狂_七  阅读(61)  评论(0编辑  收藏  举报