我有以下代码:
var orders = context.Orders
.Include("Clients")
.GroupBy(i => i.Clients.ClientName)
.Select(i => i.OrderByDescending(it => it.OrderDate).FirstOrDefault());
我想只获得每个客户的最后订单。我从这里得到的代码的基础Remove duplicates in the list using linq,来自弗雷迪的回答。 (我包括"客户"因为订单有ClientId但没有客户名称,结果将显示在网格中,包括我从客户端获取的客户名称)。 这很正常。
我的问题:
是否可以使用asp.net实体数据源控件执行此操作? 是否可以在asp.net实体数据源控件中以某种方式使用FirstOrDefault?
答案 0 :(得分:1)
如果您将Include
移至查询结尾...
var orders = context.Orders
.GroupBy(i => i.Clients.ClientName)
.Select(i => i.OrderByDescending(it => it.OrderDate).FirstOrDefault())
.Include("Clients");
......你会得到Order
个客户。
使用原始Include
后,查询形状会在应用Include
后发生变化。 This always makes Include
ineffective。您可以将其移至查询的末尾,因为即使在分组后,查询仍会返回Order
,因此Include
适用。
但请注意,这是一个巨大的矫枉过正。从数据库中查询整个Client
条记录,实现整个Client
个对象,最后只显示其名称。将所需数据投影到完全包含要显示的数据的DTO要好得多。例如:
var orders = context.Orders
.GroupBy(i => i.Clients.ClientName)
.Select(i => i.OrderByDescending(it => it.OrderDate).FirstOrDefault())
.Select(o => new OrderDto
{
o.OrderNumber,
o. ... // More Order properties
Client = o.Clients.Name
});
DTO应该是包含这些属性的类。
我不知道实体数据源控件。从我在MSDN文档中看到的情况来看,它似乎太受限制甚至不能充分调整查询以获得每个客户端的最后订单。它需要一个实体集,没有DTO。
答案 1 :(得分:0)
而不是致电OrderbyDescending
尝试使用max
按照说明操作here
答案 2 :(得分:0)
我发现here可以使用EntityDataSource:
Select="top(1) it.[OrderDate]"
但是,如果您想要Order by DESC
,top
将在Order by DESC
之前执行。
如果您希望在Order by
之前执行top
,换句话说要获取最后一个项目,而不是top
在代码中执行此操作:
protected void entityDataSource_Selecting(object sender,EntityDataSourceSelectingEventArgs e)
{
e.SelectArguments.MaximumRows = 1;
}
我在Qustion and Answer中从link获得了所有这些。
答案 3 :(得分:0)
我发现我可以使用问题和答案中Filter with EntityDatasource in ASP.NET webforms中所示的EntityDataSource
QueryCreated
事件。
在我写这个问题的情况下
protected void EntityDataSource1_QueryCreated(object sender, QueryCreatedEventArgs e)
{
var ordersQuery = e.Query.OfType<Orders>();
e.Query = ordersQuery.Include("Clients")
.GroupBy(i => i.Clients.ClientName)
.Select(i => i.OrderByDescending(it => it.OrderDate).FirstOrDefault());
}