【问题标题】:Getting two most recent entries to two given dates with EF 6使用 EF 6 获取两个给定日期的两个最新条目
【发布时间】:2017-06-15 23:09:32
【问题描述】:

(抱歉标题含糊,不知道该怎么写。)

这是 .NET 4.7、EF 6.1。我有两张表:一组产品和一组历史价格。我需要编写一些代码来获取截至两个提供日期(开始和结束)的所有产品及其价格的列表。这本质上是一份报告,用于查看产品价格在两个日期之间的变化情况,但我只需要开始/结束价格,而不是中间的所有价格。

我能想到的唯一方法是类似于下面的代码。我会运行两次——一次用于开始日期,一次用于结束日期——然后我会将这两个列表加入到我需要的模型类型列表中。我无法为我的生活弄清楚如何做到这一点。 我应该如何做到这一点?

简化的表格布局:

Product        HistoricalPrice
-------        ---------------
-Id            -Id
-Name          -ProductId
               -ModifiedAt
               -NewPrice

这是我尝试使用的代码。 Product 是对HistoricalPriceProduct 的引用,它是类的一部分,并由ProductId 字段引用。我需要从此代码的最终结果中获取产品名称/ID。

var historicalStartPrices = await _context.ProductHistoricalPrices

    // need to include the product itself
    .Include(p => p.Product)

    // only get prices that come before the start date
    .Where(p => p.ModifiedAt <= start)

    // order from most recent -> oldest by modified date
    .OrderByDescending(p => p.ModifiedAt)

    // group prices by the product ID
    .GroupBy(p => p.ProductId)

    // take only the first result for each product ID
    .Select(g => g.First())

    // enumerate the results
    .ToListAsync();

该代码抛出此异常:

NotSupportedException:方法“First”只能用作最终查询操作。请考虑在此实例中使用“FirstOrDefault”方法。

如果我切换到FirstOrDefault,那么所有Products 都是空的。

【问题讨论】:

    标签: c# .net entity-framework


    【解决方案1】:

    为什么需要在产品历史价格中包含产品?这些表不是相关的吗? 也许对您的代码进行简单的修改将有助于实现您的目标:

    var historicalStartPrices = await _context.ProductHistoricalPrices;
    
    // only get prices that come between start and end dates
    .Where(p => p.ModifiedAt >= start && p.ModifiedAt <= end
    
    // order from most recent -> oldest by modified date
    .OrderByDescending(p => p.ModifiedAt)
    
    // take only prices foreach products in ProductHistoricalPrices
    .Select(g => g.NewPrice)
    
    // enumerate the results
    .ToListAsync();
    

    【讨论】:

    • 我刚刚将此添加到问题中,很抱歉造成混淆。 Product 是对HistoricalPriceProduct 的引用,它是类的一部分,并由ProductId 字段引用。我需要从此代码的最终结果中获取产品名称/ID。
    【解决方案2】:

    这可能在您的代码中的其他地方引用,但p.Product 指的是什么?我在您的表格中没有看到这样的通用字段。

    此外,如果您尝试获取需要位于您正在查询的字段旁边的 Id 的第一个结果。

    假设第一个查询不是必需的,您的查询可能看起来相同:

    .Where(p => p.ModifiedAt <= start)
    .OrderByDescending(p => p.ModifiedAt)
    .GroupBy(p => p.ProductId.First())
    .ToListAsync();
    

    如果您确实需要引用另一个表中的项目,您可以将该值存储在一个变量中,或者您可以简单地检索您最近的条目:`query.Where(p => p.ModifiedAt

    【讨论】:

    • 我刚刚将此添加到问题中,很抱歉造成混淆。 Product 是对HistoricalPriceProduct 的引用,它是类的一部分,并由ProductId 字段引用。我需要从此代码的最终结果中获取产品名称/ID。
    【解决方案3】:

    您的问题的解决方案(时间范围内每个产品的初始价格和最终价格)是让您的 Linq 查询如下所示:

    var historicalPrices = await _context.ProductHistoricalPrices.Where(x => x.ModifiedAt >= startDate && x.ModifiedAt <= endDate).Select(x => new
        {
         ProductId = x.ProductId,
         ProductName = x.Product.Name,
         Price = x.NewPrice,
         ModificationDate = x.ModifiedAt
        }).GroupBy(x => x.ProductId).Select(x => new
    {
      ProductName = x.FirstOrDefault().ProductName,
      InitialPrice = x.OrderBy(x => x.ModificationDate).FirstOrDefault().Price,
      FinalPrice = x.OrderByDescending(x => x.ModificationDate).FirstOrDefault().Price
    }).ToListAsync();
    

    【讨论】:

      猜你喜欢
      • 2017-11-04
      • 2019-09-13
      • 1970-01-01
      • 1970-01-01
      • 2021-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多