提问



我一直在寻找SelectSelectMany之间的区别,但我找不到合适的答案。我需要了解使用LINQ To SQL时的区别,但我发现的只是标准数组示例。


有人可以提供LINQ To SQL示例吗?

最佳参考


SelectMany展平返回列表列表的查询。例如


public class PhoneNumber
{
    public string Number { get; set; }
}

public class Person
{
    public IEnumerable<PhoneNumber> PhoneNumbers { get; set; }
    public string Name { get; set; }
}

IEnumerable<Person> people = new List<Person>();

// Select gets a list of lists of phone numbers
IEnumerable<IEnumerable<PhoneNumber>> phoneLists = people.Select(p => p.PhoneNumbers);

// SelectMany flattens it to just a list of phone numbers.
IEnumerable<PhoneNumber> phoneNumbers = people.SelectMany(p => p.PhoneNumbers);

// And to include data from the parent in the result: 
// pass an expression to the second parameter (resultSelector) in the overload:
var directory = people
   .SelectMany(p => p.PhoneNumbers,
               (parent, child) => new { parent.Name, child.Number });


.NET小提琴现场演示[29]

其它参考1


选择很多就像在SQL中的交叉连接操作,它需要交叉产品
例如,如果我们有[30]


Set A={a,b,c}
Set B={x,y}


选择多个可用于获取以下设置


{ (x,a) , (x,b) , (x,c) , (y,a) , (y,b) , (y,c) }


请注意,这里我们采用可以从集合A和集合B的元素中进行的所有可能组合。


这是您可以尝试的LINQ示例


List<string> animals = new List<string>() { "cat", "dog", "donkey" };
List<int> number = new List<int>() { 10, 20 };

var mix = number.SelectMany(num => animals, (n, a) => new { n, a });


混合物将具有扁平结构的以下元素


{(10,cat), (10,dog), (10,donkey), (20,cat), (20,dog), (20,donkey)}

其它参考2





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

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



  1. 罗纳尔多

  2. 梅西

  3. 法布雷加斯

  4. 罢了

  5. 卡西利亚斯



...

其它参考3


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


更多详情,请参阅此博客文章。[31]

其它参考4


SelectMany有几个重载。其中一个允许您在遍历层次结构时跟踪父级和子级之间的任何关系。


示例:假设您具有以下结构:League -> Teams -> Player


您可以轻松返回平面的球员集合。但是,您可能会失去对玩家所属团队的任何引用。


幸运的是,为此目的存在过载:


var teamsAndTheirLeagues = 
         from helper in leagues.SelectMany
               ( l => l.Teams
                 , ( league, team ) => new { league, team } )
                      where helper.team.Players.Count > 2 
                           && helper.league.Teams.Count < 10
                           select new 
                                  { LeagueID = helper.league.ID
                                    , Team = helper.team 
                                   };


前面的例子取自Dan的IK博客。我强烈建议你看一下。[32]

其它参考5


我理解SelectMany像连接快捷方式一样工作。


所以你可以:


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

其它参考6


选择是从源元素到结果元素的简单一对一投影。选择-
当查询表达式中有多个from子句时使用many:原始序列中的每个元素用于生成新序列。

其它参考7


某些SelectMany可能没有必要。低于2的查询给出相同的结果。


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

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


对于1对多的关系,



  1. 如果从1开始,需要SelectMany,它会使许多人变平。

  2. 如果从Many开始,则不需要SelectMany。 (仍然可以从1过滤,这也比标准联接查询更简单)






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

其它参考8


没有太过技术化 - 有许多组织的数据库,每个组织都有很多用户: -


var orgId = "123456789";

var userList1 = db.Organizations
                   .Where(a => a.OrganizationId == orgId)
                   .SelectMany(a => a.Users)
                   .ToList();

var userList2 = db.Users
                   .Where(a => a.OrganizationId == orgId)
                   .ToList();


两者都返回所选组织的相同 ApplicationUser列表。


第一个项目从组织到用户,第二个直接查询Users表。

其它参考9


只是为了一个可以帮助一些功能程序员的替代视图:



  • Selectmap

  • SelectManybind(或flatMap为您的Scala/Kotlin人)


其它参考10


当查询返回一个字符串(一个char数组)时,它会更清楚:


例如,如果列表Fruits包含apple


选择返回字符串:


Fruits.Select(s=>s) 

[0]: "apple"


SelectMany展平字符串:


Fruits.SelectMany(s=>s)

[0]: 97  'a'
[1]: 112 'p'
[2]: 112 'p'
[3]: 108 'l'
[4]: 101 'e'

其它参考11


还有一个例子可以使用SelectMany + Select来累积子数组对象数据。


假设我们有用户手机:


class Phone { 
    public string BasePart = "555-xxx-xxx"; 
}

class User { 
    public string Name = "Xxxxx";
    public List<Phone> Phones; 
}


现在我们需要选择所有手机所有用户的BaseParts:


var usersArray = new List<User>(); // array of arrays
List<string> allBaseParts = usersArray.SelectMany(ua => ua.Phones).Select(p => p.BasePart).ToList();

其它参考12


这是理解我认为的最佳方式。


            var query =
            Enumerable
                .Range(1, 10)
                .SelectMany(ints => Enumerable.Range(1, 10), (a, b) => $"{a} * {b} = {a * b}")
                .ToArray();

        Console.WriteLine(string.Join(Environment.NewLine, query));

        Console.Read();


乘法表示例。