我一直在寻找和之间的区别Select
,SelectMany
但找不到合适的答案。我需要学习使用LINQ To SQL的区别,但我发现的只是标准数组示例。
有人可以提供LINQ To SQL示例吗?
我一直在寻找和之间的区别Select
,SelectMany
但找不到合适的答案。我需要学习使用LINQ To SQL的区别,但我发现的只是标准数组示例。
有人可以提供LINQ To SQL示例吗?
Answers:
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 });
选择许多对象就像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)}
SelectMany
的。而是,这是一种SelectMany
可以使用的方法,但实际上不是正常的使用方法。
Where
在SelectMany之后也要证明病情,那就太好了
SelectMany()
使您可以以某种方式折叠多维序列,而这种折叠本来需要一秒钟Select()
或循环。
有关更多详细信息,请参见此博客文章。
有几个重载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博客。我强烈建议您看一下。
我知道SelectMany
可以像加入捷径一样工作。
所以你可以:
var orders = customers
.Where(c => c.CustomerName == "Acme")
.SelectMany(c => c.Orders);
某些SelectMany可能不是必需的。下面两个查询给出相同的结果。
Customers.Where(c=>c.Name=="Tom").SelectMany(c=>c.Orders)
Orders.Where(o=>o.Customer.Name=="Tom")
对于一对多关系,
from o in Orders
join c in Customers on o.CustomerID equals c.ID
where c.Name == "Tom"
select o
不用太技术-具有许多组织的数据库,每个组织都有许多用户:-
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列表。
第一个“项目”从组织到用户,第二个直接查询“用户”表。
考虑这个例子:
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();
因此,如您所见,由于“ SelectMany”变平并在多个序列中投影,因此已从query2中删除了诸如“ I”或“ like”之类的重复值。但是query1返回字符串数组的序列。并且由于query1中有两个不同的数组(第一个和第二个元素),因此不会删除任何内容。
另一个示例如何使用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();
usersArray.SelectMany(ua => ua.Phones.Select(p => p.BasePart))
这是一个带有初始化的小集合以进行测试的代码示例:
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; }
}
这是理解我的想法的最好方法。
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();
乘法表示例。