上下文: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();
在英语中,这是在寻找在日期范围内执行最后一个订单的下五个帐户。但是,也有可以取消的订单,因此我们必须在执行该Max时排除42的OrderStatus。
问题围绕多对多表中过滤的Max日期。增加的复杂性是我们需要按照过滤的最大值进行排序,我们必须完成上述所有操作而不会破坏我们的预期加载(即连接必须通过Where中的投影来完成,而不是使用.Join)。我不确定如何进行此查询而不会导致10x的结果比它应该更复杂。我讨厌做连接来过滤ao.OrderStatus / Max的DateToExecute 3次(一次用于startDate,一次用于stopDate,一次用于排序)。显然,IsBetween不起作用。
有关如何执行此查询的任何想法,以这种方式排序,以相当有效的方式生成SQL吗?
答案 0 :(得分:1)
在此处使用匿名类型可能会有所帮助:
DateTime startDateInclusive = xxxx;
DateTime stopDateExclusive = yyy;
var query = Db.Accounts
.Select(account => new {
Account = account,
MaxDate = account.AccountOrders.Select(ao => ao.Order).Where(o => o.OrderStatus != 42).Max(o => o.DateToExecute)
})
.Where(a => a.MaxDate >= startDateInclusive && a.MaxDate < stopDateExclusive)
.OrderBy(a => a.MaxDate)
.Select(a => a.Account)
.Include(a => a.AccountOrders.Select(ao => ao.Order.Ordereditems.Select(oi => oi.Item)));
var results = query.Take(5).ToList();
这是未经测试的,因为我没有任何数据源可供测试。但它可能是您需要做的最简单的方法。