Groupby,选择EF Ccore 3.1

时间:2021-06-21 17:18:18

标签: c# linq .net-core entity-framework-core

我有三个这样的表:

public partial class PriceSite
{
    public DateTime ValidFromGmtDtm { get; set; }        
    public long PriceSiteId { get; set; }
    public virtual ICollection<PriceSiteProduct> PriceSiteProduct { get; set; }
}

public partial class PriceSiteProduct
{
    public long PriceSiteId { get; set; }
    public long ProductId { get; set; }
    public virtual Product Product { get; set; }     
}

public partial class Product
{
    public string ProductCd { get; set; }
    public string ProductNm { get; set; }       
    public long ProductId { get; set; }
    public virtual ICollection<PriceSiteProduct> PriceSiteProduct { get; set; }
}

我们需要按 Productname 对数据进行分组,并选择具有最高 ValidFromGmtDtm (Pricesite) 的产品。

我试过这个查询

using (var dbContext = _dbContextProvider.DbContext)
{
    var data = from t1 in dbContext.PriceSite
               join t2 in dbContext.PriceSiteProduct 
                           on t1.PriceSiteId equals t2.PriceSiteId
               join t3 in dbContext.Product
                           on t2.ProductId equals t3.ProductId
               where t1.ValidFromGmtDtm > shellSiteNotification.ValidFromDtm
               select new
                      {
                          PriceSiteId = t1.PriceSiteId,
                          ValidFrom = t1.ValidFromGmtDtm,
                          ProductId = t3.ProductId,
                          ProductNm = t3.ProductNm,
                          ProductValues = t3.PumpPriceProduct
                      };

    var res1 = data.ToList();

    var data2 = from element in res1
                group element by element.ProductNm into groups
                select groups.OrderByDescending(p => p.ValidFrom).FirstOrDefault();
}

运行此查询时出现超时错误。

我也试过这个查询:

var grouped = from priceSite in _dbContextProvider.DbContext.PriceSite
              where priceSite.ValidFromGmtDtm < shellSiteNotification.ValidFromDtm
              from priceSiteProduct in priceSite.PriceSiteProduct
              group priceSiteProduct by priceSiteProduct.Product.ProductNm into produtGroup
              select new
                     {
                          ProductNamKey = produtGroup.Key,
                          produtGroup = produtGroup.OrderByDescending(x => x.PriceSite.ValidFromGmtDtm)
                     };

此代码引发运行时错误,因为我们无法访问 EF Core 中 select 中的导航属性。

我还尝试了另一个查询 - 但这也会导致超时

var result = from s in _dbContextProvider.FreshReadOnlyPricingDbContext.PriceSite
             from r in s.PriceSiteProduct
             let p = r.Product
             select new
                    {
                        PriceSiteId = s.PriceSiteId,
                        ValidFrom = s.ValidFromGmtDtm,
                        ProductId = p.ProductId,
                        ProductNm = p.ProductNm,
                        ProductValues = p.PumpPriceProduct
                    };
    
var list = result.ToList();

1 个答案:

答案 0 :(得分:0)

已知EF和SQL限制,分组后无法获取项目。仅支持 Key 和聚合结果。所以基本上 EF 建议将 ToList() 放在分组之前,这意味着您将向客户端加载数百万条记录。

如果没有可以有效执行此操作的第三方扩展程序,您可以使用以下解决方法:

using (var dbContext = _dbContextProvider.DbContext)
{
    var dataQuery = 
        from t1 in dbContext.PriceSite
        join t2 in dbContext.PriceSiteProduct 
                    on t1.PriceSiteId equals t2.PriceSiteId
        join t3 in dbContext.Product
                    on t2.ProductId equals t3.ProductId
        where t1.ValidFromGmtDtm > shellSiteNotification.ValidFromDtm
        select new
        {
            PriceSiteId = t1.PriceSiteId,
            ValidFrom = t1.ValidFromGmtDtm,
            ProductId = t3.ProductId,
            ProductNm = t3.ProductNm,
            ProductValues = t3.PumpPriceProduct
        };

    var query = 
        from key in dataQuery.Select(d => new { d.ProductNm }).Distinct()
        from d in dataQuery.Where(d => d.ProductNm == key.ProductNm)
            .OrderByDescending(d => d.ValidFrom)
            .Take(1)
        select d; 

    var result = query.ToList();
}