上下文:EF4、C#、.NET4、SQL2008/R2
重现问题的表/实体:
Account (long Id, string Name, etc.)
Order (long Id, DateTime DateToExecute, int OrderStatus, etc.)
AccountOrder (long Id, long AccountId, long OrderId)
<- 是的,一个帐户可能有多个订单,同样,一个订单可能与多个帐户相关联。OrderedItem (long Id, long OrderId, long ItemId, etc)
<- 一个订单可能有很多商品,我们希望预先加载这些商品(我意识到这会影响性能/数据大小)。
非常适合工作的伪代码(几乎是真实代码):
DateTime startDateInclusive = xxxx;
DateTime stopDateExclusive = yyy;
var query = Db.Accounts.Include(a => a.AccountOrders.Select(ao => ao.Order.Ordereditems.Select(oi => oi.Item)))
.Where(account =>
account.AccountOrders.Where(ao => ao.OrderStatus != 42)
.Max(ao => ao.DateToExecute).IsBetween(startDateInclusive, stopDateExclusive))
.OrderBy(account =>
account.AccountOrders.Where(ao => ao.OrderStatus != 42)
.Max(ao => ao.DateToExecute));
var results = query.Take(5).ToList();
在英语中,这是寻找在一个日期范围内执行最后一个订单的下 5 个帐户。但是,也有可以取消的订单,因此我们在执行该 Max 时必须排除 42 的 OrderStatus。
问题围绕多对多表的过滤最大日期展开。一个额外的复杂性是我们需要按过滤后的最大值进行排序,并且我们必须在不破坏我们急切加载的情况下完成上述所有操作(即,连接必须通过 Where 中的投影完成,而不是使用 .Join)。我不确定如何执行此查询,而不会使结果比应有的复杂 10 倍。我不想进行连接以过滤 ao.OrderStatus/Max DateToExecute 3 次(一次用于 startDate,一次用于 stopDate,一次用于排序)。显然 IsBetween 不起作用。
关于如何以一种相当有效的方式对生成的 SQL 执行此查询(以这种方式排序)的任何想法?