如何在 EF4 中按筛选的 Max 查询进行查询和排序

本文关键字:查询 Max 排序 筛选 EF4 | 更新日期: 2023-09-27 18:31:36

>上下文: 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 个帐户,这些帐户的最后一个订单将在某个日期范围内执行。但是,也有一些订单可以取消,因此我们必须在执行该最大值时排除订单状态 42。

问题围绕此筛选的多对多表中的最大日期展开。增加的复杂性是我们需要按过滤后的最大值进行排序,并且我们必须在不破坏我们急切加载的情况下完成上述所有操作(即连接必须通过 Where 中的投影完成,而不是使用 .加入)。我不确定如何在结果比应有的复杂 10 倍的情况下进行此查询。我不想做连接来过滤 ao。OrderStatus/Max the DateToExecute 3次(一次用于开始日期,一次用于停止日期,一次用于排序)。显然,IsT之間不起作用。

关于如何以这种方式对生成的 SQL 以相当有效的方式执行此查询的任何想法?

如何在 EF4 中按筛选的 Max 查询进行查询和排序

在此处使用匿名类型可能会有所帮助:

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();
这是未经测试的,

因为我没有任何数据源可以测试。 但这可能是您需要做的最简单的方法。