Select和SelectMany之间的区别

这篇博客讨论了在LINQ to SQL中Select和SelectMany操作符的区别。Select是一对一的投影,而SelectMany用于将序列展开成新的序列,类似于SQL中的交叉连接。文中通过示例解释了何时以及如何使用这两个操作符,特别是在处理一对多关系时。博客还提到了SelectMany在处理层次结构和累积子数组数据时的作用。
摘要由CSDN通过智能技术生成

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

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


#1楼

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


#2楼

选择许多对象就像SQL中的交叉连接操作一样需要交叉乘积。
例如,如果我们有

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)}

#3楼

在此处输入图片说明

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. 布斯克茨

...


#4楼

某些SelectMany可能不是必需的。 以下2个查询给出相同的结果。

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

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

对于一对多关系,

  1. 如果从“ 1”开始,则需要SelectMany,它将使许多数目变平。
  2. 如果从“许多”开始,则不需要SelectMany。 ( 仍然可以从“ 1”进行过滤 ,这比标准的连接查询还简单)

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

#5楼

这是了解我的想法的最好方法。

            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();

乘法表示例。


#6楼

不用太技术-具有许多组织的数据库,每个组织都有许多用户:-

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列表。

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


#7楼

更清楚的是查询何时返回字符串(char数组):

例如,如果列表“水果”包含“苹果”

“选择”返回字符串:

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'

#8楼

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博客 。 我强烈建议您看一下。


#9楼

仅出于替代的观点,可能对某些功能性程序员有所帮助:

  • Select map
  • SelectManybind (或Scala / Kotlin人员的flatMap

#10楼

另一个示例如何使用SelectMany + Select来累积子数组对象数据。

假设我们有用户在使用他们的电话:

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

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

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

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

#11楼

这是一个带有初始化的小集合以进行测试的代码示例:

class Program
{
    static void Main(string[] args)
    {
        List<Order> orders = new List<Order>
        {
            new Order
            {
                OrderID = "orderID1",
                OrderLines = new List<OrderLine>
                {
                    new OrderLine
                    {
                        ProductSKU = "SKU1",
                        Quantity = 1
                    },
                    new OrderLine
                    {
                        ProductSKU = "SKU2",
                        Quantity = 2
                    },
                    new OrderLine
                    {
                        ProductSKU = "SKU3",
                        Quantity = 3
                    }
                }
            },
            new Order
            {
                OrderID = "orderID2",
                OrderLines = new List<OrderLine>
                {
                    new OrderLine
                    {
                        ProductSKU = "SKU4",
                        Quantity = 4
                    },
                    new OrderLine
                    {
                        ProductSKU = "SKU5",
                        Quantity = 5
                    }
                }
            }
        };

        //required result is the list of all SKUs in orders
        List<string> allSKUs = new List<string>();

        //With Select case 2 foreach loops are required
        var flattenedOrdersLinesSelectCase = orders.Select(o => o.OrderLines);
        foreach (var flattenedOrderLine in flattenedOrdersLinesSelectCase)
        {
            foreach (OrderLine orderLine in flattenedOrderLine)
            {
                allSKUs.Add(orderLine.ProductSKU);
            }
        }

        //With SelectMany case only one foreach loop is required
        allSKUs = new List<string>();
        var flattenedOrdersLinesSelectManyCase = orders.SelectMany(o => o.OrderLines);
        foreach (var flattenedOrderLine in flattenedOrdersLinesSelectManyCase)
        {
            allSKUs.Add(flattenedOrderLine.ProductSKU);
        }

       //If the required result is flattened list which has OrderID, ProductSKU and Quantity,
       //SelectMany with selector is very helpful to get the required result
       //and allows avoiding own For loops what according to my experience do code faster when
       // hundreds of thousands of data rows must be operated
        List<OrderLineForReport> ordersLinesForReport = (List<OrderLineForReport>)orders.SelectMany(o => o.OrderLines,
            (o, ol) => new OrderLineForReport
            {
                OrderID = o.OrderID,
                ProductSKU = ol.ProductSKU,
                Quantity = ol.Quantity
            }).ToList();
    }
}
class Order
{
    public string OrderID { get; set; }
    public List<OrderLine> OrderLines { get; set; }
}
class OrderLine
{
    public string ProductSKU { get; set; }
    public int Quantity { get; set; }
}
class OrderLineForReport
{
    public string OrderID { get; set; }
    public string ProductSKU { get; set; }
    public int Quantity { get; set; }
}

#12楼

我了解SelectMany像联接快捷方式一样工作。

所以你可以:

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

#13楼

SelectMany()使您可以以某种方式折叠多维序列,否则该方式将需要第二个Select()或循环。

有关更多详细信息, 请参见此博客文章


#14楼

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 Fiddle上的实时演示

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值