我一直在搜索Select和SelectMany之间的区别,但我还没有找到合适的答案。我需要学习使用LINQ to SQL时的差异,但我所找到的都是标准数组示例。

有人能提供一个LINQ到SQL的例子吗?


当前回答

SelectMany()的正式描述是:

将序列的每个元素投射到IEnumerable上并展开 产生的序列变成一个序列。

SelectMany()将结果序列平铺成一个序列,并对其中的每个元素调用结果选择器函数。

class PetOwner
{
    public string Name { get; set; }
    public List<String> Pets { get; set; }
}

public static void SelectManyEx()
{
     PetOwner[] petOwners =
         { new PetOwner { Name="Higa, Sidney",
              Pets = new List<string>{ "Scruffy", "Sam" } },
           new PetOwner { Name="Ashkenazi, Ronen",
              Pets = new List<string>{ "Walker", "Sugar" } },
           new PetOwner { Name="Price, Vernette",
              Pets = new List<string>{ "Scratches", "Diesel" } } };

// Query using SelectMany().
IEnumerable<string> query1 = petOwners.SelectMany(petOwner => petOwner.Pets);

Console.WriteLine("Using SelectMany():");

// Only one foreach loop is required to iterate
// through the results since it is a
// one-dimensional collection.
foreach (string pet in query1)
{
    Console.WriteLine(pet);
}

// This code shows how to use Select()
// instead of SelectMany().
IEnumerable<List<String>> query2 =
    petOwners.Select(petOwner => petOwner.Pets);

Console.WriteLine("\nUsing Select():");

// Notice that two foreach loops are required to
// iterate through the results
// because the query returns a collection of arrays.
foreach (List<String> petList in query2)
{
    foreach (string pet in petList)
    {
        Console.WriteLine(pet);
    }
    Console.WriteLine();
}
}

/*
   This code produces the following output:

    Using SelectMany():
    Scruffy
    Sam
    Walker
    Sugar
    Scratches
    Diesel

   Using Select():
   Scruffy
   Sam

   Walker
   Sugar

   Scratches
   Diesel
  */

主要的区别是每个方法的结果,而SelectMany()返回一个扁平的结果;Select()返回一个列表的列表,而不是一个扁平的结果集。

因此,SelectMany的结果是一个列表

{斯库菲,山姆,沃克,甜甜,划痕,迪塞尔}

你可以迭代每一项。但是对于select的结果,您需要一个额外的foreach循环来遍历结果,因为查询返回一个数组集合。

其他回答

我理解SelectMany工作起来像一个连接快捷方式。

所以你可以:

var orders = customers
             .Where(c => c.CustomerName == "Acme")
             .SelectMany(c => c.Orders);

SelectMany()允许您以一种需要第二个Select()或循环的方式折叠多维序列。

更多细节请参见这篇博客文章。

var players = db.SoccerTeams.Where(c => c.Country == "Spain")
                            .SelectMany(c => c.players);

foreach(var player in players)
{
    Console.WriteLine(player.LastName);
}

De Gea 阿尔芭 科斯塔 别墅 Busquets

...

Some SelectMany可能不需要。以下2个查询给出相同的结果。

Customers.Where(c=>c.Name=="Tom").SelectMany(c=>c.Orders)

Orders.Where(o=>o.Customer.Name=="Tom")

对于一对多关系,

如果从“1”开始,则需要SelectMany,它将平展many。 如果从“Many”开始,则不需要SelectMany。(仍然能够从“1”中过滤,这也比以下标准的连接查询更简单)


from o in Orders
join c in Customers on o.CustomerID equals c.ID
where c.Name == "Tom"
select o

想想这个例子:

        var array = new string[2]
        {
            "I like what I like",
            "I like what you like"
        };
        //query1 returns two elements sth like this:
        //fisrt element would be array[5]  :[0] = "I" "like" "what" "I" "like"
        //second element would be array[5] :[1] = "I" "like" "what" "you" "like"
        IEnumerable<string[]> query1 = array.Select(s => s.Split(' ')).Distinct();

        //query2 return back flat result sth like this :
        // "I" "like" "what" "you"
        IEnumerable<string> query2 = array.SelectMany(s => s.Split(' ')).Distinct();

因此,正如你所看到的,像“I”或“like”这样的重复值已从query2中删除,因为“SelectMany”将在多个序列上平坦和投影。 但是query1返回字符串数组序列。由于query1中有两个不同的数组(第一个和第二个元素),因此不会删除任何东西。