使用Linq为每个客户带回最后3,4…n个订单

使用Linq为每个客户带回最后3,4…n个订单,linq,entity-framework,lambda,Linq,Entity Framework,Lambda,我有一个客户订单数据库。 我想使用Linq to EF查询数据库,为每个客户带回最近的3,4…n订单 注: 客户1在上一个小时内可能刚下了12个订单;但是,客户2可能从上周起就没有做过 我一辈子都搞不懂如何用linq lambda表达式编写查询来获取数据集 有什么好主意吗 编辑: 客户和订单是一种简化。我查询的表实际上是到各种web服务的出站消息的记录。这似乎更容易描述为客户和订单。关系是一样的。 我正在构建一个任务,用于检查每个web服务的最后n条消息,以查看是否存在任何故障。我们需要Web服

我有一个客户订单数据库。 我想使用Linq to EF查询数据库,为每个客户带回最近的3,4…n订单

注: 客户1在上一个小时内可能刚下了12个订单;但是,客户2可能从上周起就没有做过

我一辈子都搞不懂如何用linq lambda表达式编写查询来获取数据集

有什么好主意吗

编辑: 客户和订单是一种简化。我查询的表实际上是到各种web服务的出站消息的记录。这似乎更容易描述为客户和订单。关系是一样的。 我正在构建一个任务,用于检查每个web服务的最后n条消息,以查看是否存在任何故障。我们需要Web服务的半实时运行状况

@科雷森沃德 我的桌子看起来有点像这样: MessageID、WebserviceID、SentTime、状态、消息、错误、

或者从客户/订单上下文中,如果它使其更容易: OrderID、CustomerID、StatusChangedDate、Status、WidgetName、注释

编辑2: 我终于想出了办法 给@StephenChung的帽子贴士,他基本上提出了完全相同的建议,但采用了经典的linq

var q=myTable.Whered=>d.EndTime>DateTime.Now.AddDays-1 .GroupByg=>g.ConfigID .Selectg=>new { ConfigID=g.密钥, Data=g.orderbydegendingd=>d.EndTime .Take3.Selects=>new { s、 地位, s、 哨兵 } }托利斯特先生;


执行确实需要一段时间。所以我不确定这是否是最有效的表达方式。

这个怎么样?我知道它可以用于常规收藏,但不知道EF

yourCollection.OrderByDescending(item=>item.Date).Take(n);
这将需要最后4个订单。具体查询取决于表/实体结构


顺便说一句:您可以接受x作为订单。因此,您可以像这样阅读:在order.CustomerID等于1的情况下获取订单,按order.Date对订单进行排序,并获取前4行。

您可以使用SelectMany来实现此目的:

customers.SelectMany(x=>x.orders.OrderByDescending(y=>y.Date).Take(n)).ToList();

这将返回按客户分组的订单。

有人可能会在这里纠正我,但我认为使用linq进行单个查询可能非常困难,如果不是不可能的话。我会使用存储过程和类似的东西

select 
    *
    ,RANK() OVER  (PARTITION BY c.id ORDER BY o.order_time DESC) AS 'RANK'
from 
    customers c 
inner join 
    order o
on 
    o.cust_id = c.id
where 
    RANK < 10 -- this is "n"

我已经有一段时间没有使用这种语法了,所以它可能不太正确,但是如果我理解这个问题,那么我认为这是最好的方法。

如果有订单,这应该给出每个客户的最后3个订单:

from o in db.Orders
group o by o.CustomerID into g
select new {
  CustomerID=g.Key,
  LastOrders=g.OrderByDescending(o => o.TimeEntered).Take(3).ToList()
}
但是,我怀疑这将迫使数据库在为每个客户选择最后3个订单之前返回整个Orders表。检查生成的SQL语句


如果需要优化,则必须手动构造一个SQL,只返回最后3个SQL,然后将其放入视图中。

到目前为止,您有什么发现吗?另外,您能告诉我们有关您正在查询的表的任何信息吗?如果您有一个具有标识值的列,这应该很容易。@coreysunbold我已经输入了我的表的外观。@coreysunbold我还将我的表作为部分解决方案。不过,我不确定它有多理想。这与@StephenChung提出的基本相同。需要一个orderby才能工作,我从来没有在linq to sql或EF中使用过它,我可以试试。@Paul creasy,为什么要使用orderby?我在查询中有它,我没有用LIQ2SQL测试它只是猜测它工作,但它不工作在LIQ2NHiBiNess至少NHiBurnter 2.XI试图使用这一点,但我不能得到.Script许多语法是正确的。我已经建立了一个样本表布局。如果你能更新你必须使用的东西,那将是非常棒的。这只是给出了任何客户的最后n个订单,你是对的。我将对下面的SelectMany方法进行升级,它应该适用于每一位客户。对于linq来说,这一点都不难。它甚至更简单。使用linq是的,但我不太确定EF的linq to sql,但我不想费心去测试它。应该是OrderByDescending,这样就可以了,但只对1个客户有效。这与我最终提出的基本相同。但是在lambda语法中。所以请投我一票。
select 
    *
    ,RANK() OVER  (PARTITION BY c.id ORDER BY o.order_time DESC) AS 'RANK'
from 
    customers c 
inner join 
    order o
on 
    o.cust_id = c.id
where 
    RANK < 10 -- this is "n"
from o in db.Orders
group o by o.CustomerID into g
select new {
  CustomerID=g.Key,
  LastOrders=g.OrderByDescending(o => o.TimeEntered).Take(3).ToList()
}