我必须要有实体,这些实体通过orderID(一对多Relationshiphoip)彼此关联:
Request Order
-reqID -orderID**
-orderID** -name
-name
如何使用linq从“请求”中选择“订单”?
IQueryable<Request> requests = GetList();
IQueryable<Order> orders = requests.Select(x => x.Order);
建议我使用此功能,但不能正常工作
select returns "IQueryable<ICollection<Order>>" type.
答案 0 :(得分:3)
要使所有与订单关联的订单在一个列表中变平,请使用SelectMany
var orders = requests.SelectMany(x => x.Order);
答案 1 :(得分:0)
首先介绍如何在实体框架中设计表关系。然后回到您的问题
很显然,您的Requests
与Orders
之间存在某种关系。这似乎是一对多关系:每个Order
具有零个或多个Requests
,每个Requests
都使用外键{{1}恰好属于一个Order
}。
在实体框架中,表的列是使用非虚拟属性表示的;表之间的关系使用虚拟属性表示(虚拟,因为它们在表中不是真实的列)。
如果您根据Entity Framework Code First Conventions设计一对多关系,您将拥有类似这样的类:
OrderId
这足以使实体框架检测到您的一对多关系。您的列名或表名可能会有所不同,但是您的主旨是。如果您要在类中使用与表不同的列/表名称,请使用流利的API或属性。请参阅上面的链接。
您是否注意到外键未声明为虚拟键:它是表中的实列。这两个虚拟属性不是现有值,它们描述了表之间的关系。
对于每个一对一/一对多/多对多关系,class Order
{
public int Id {get; set;}
// every order has zero or more requests (one-to-many)
public virtual ICollection<Request> Requests {get; set;}
public string Name {get; set;}
...
}
class Request
{
public int Id {get; set;}
// Every Request belongs to exactly one Order using foreign key
public int OrderId {get; set;}
public virtual Order Order {get; set;}
public string Name {get; set;}
...
}
面描述如下:
one
// Every MyClass object belongs to exactly one YourClass object using foreign key:
public int YourClassId {get; set;}
public virtual YourClass YourClass {get; set;}
面描述为:
many
因此在涉及的两个类中,多对多都有// Every MyClass has zero or more YourClass objects
public virtual ICollection<YourClass> YourClasses {get; set;}
。
已经正确设计了表关系,您的查询将很容易。您不必使用联接。使用虚拟关系:
将所有(或部分)请求(全部或部分)发给我
virtual ICollection<...>
实体框架足够聪明,可以知道需要(组)连接。
反过来:
将所有(或部分)请求与他们的订单一起给我
var result = dbContext.Orders
.Where(order => ...) // give me only the orders that ...
.Select(order => new // from every remaining order make one new object
{ // select only the properties you plan to use
Id = order.Id,
Name = order.Name,
...
Requests = order.Requests
.Where(request => ...) // give me only the requests that ...
.Select(request => new
{ // again: select only the properties you plan to use
Id = request.Id,
Name = request.Name,
...
// not needed: OrderId = request.OrderId, you already know the value!
})
.ToList(),
});
实体框架足够聪明,可以知道需要联接
但是我真的很喜欢我的加入!
好吧,如果您真的想自己设计联接,则可以执行以下操作:
var result = dbContext.Requests
.Where(request => ...) // take only the requests that ...
.Select(request => new // from every remaining request make one new object
{ // with only the properties you plan to use
Id = request.Id,
Name = request.Name,
Order = new // from the one and only Order of this Request
{ // take only the properties you plan to use
Name = request.Order.Name,
...
}
});
通过拆分Order和Request属性来考虑一种更具可读性的解决方案:
var result = dbContext.Orders
.Join(dbContext.Requests, // Join Orders with Requests
order => order.Id, // from every Order take the Id
request => request.OrderId, // from every Request take the OrderId
(order, request) => new // when they match, take the order and the request
{ // to make a new object with properties
OrderId = order.Id,
OrderName = order.Name,
RequestName = request.Name,
});
如果您想要(order, request) => new
{
Order = new
{
Id = order.Id,
Name = order.Name,
},
Request = new
{
Id = request.Id,
Name = request.Name,
},
})
,请使用Order with its Requests
代替GroupJoin
Join