【问题标题】:LINQ: combining join and group byLINQ:结合加入和分组依据
【发布时间】:2012-02-28 17:06:39
【问题描述】:

我有一个结合了联接和组的查询,但我遇到了问题。查询是这样的:

 var result = from p in Products                         
 join bp in BaseProducts on p.BaseProductId equals bp.Id                    
 group p by p.SomeId into pg                         
 select new ProductPriceMinMax { 
       SomeId = pg.FirstOrDefault().SomeId, 
       CountryCode = pg.FirstOrDefault().CountryCode, 
       MinPrice = pg.Min(m => m.Price), 
       MaxPrice = pg.Max(m => m.Price),
       BaseProductName = bp.Name  <------ can't use bp. 
 };

如您所见,它将Products 表与BaseProducts 表连接起来,并在Product 表的ID 上进行分组。但是在生成的ProductPriceMinMax中,我还需要BaseProducts表的一个属性:bp.Name,但是它不知道bp

知道我做错了什么吗?

【问题讨论】:

    标签: c# linq linq-to-sql join group-by


    【解决方案1】:

    完成此操作后

    group p by p.SomeId into pg  
    

    您不再有权访问初始 from 中使用的范围变量。即不能再谈pbp,只能谈pg

    现在,pg 是一个,因此包含多个产品。给定pg 组中的所有产品都具有相同的SomeId(因为这是您的分组依据),但我不知道这是否意味着它们都具有相同的BaseProductId

    要获得基本产品名称,您必须在pg 组中选择一个特定产品(就像您对SomeIdCountryCode 所做的那样),然后然后加入@ 987654334@。

    var result = from p in Products                         
     group p by p.SomeId into pg                         
     // join *after* group
     join bp in BaseProducts on pg.FirstOrDefault().BaseProductId equals bp.Id         
     select new ProductPriceMinMax { 
           SomeId = pg.FirstOrDefault().SomeId, 
           CountryCode = pg.FirstOrDefault().CountryCode, 
           MinPrice = pg.Min(m => m.Price), 
           MaxPrice = pg.Max(m => m.Price),
           BaseProductName = bp.Name  // now there is a 'bp' in scope
     };
    

    也就是说,这看起来很不寻常,我认为您应该退后一步,考虑一下您实际上要检索的内容。

    【讨论】:

    • 这比我们的解决方案更好:) 谢谢。
    • @AakashM 谢谢。但我正在获取 groupVariable.FirstOrDefault().column_name 的问题。当我要访问 IQueryable 变量 Result 时发生错误,标题为 “entitycommandexecutionexception 未被用户代码处理” 正文 “执行命令定义时发生错误。有关详细信息,请参阅内部异常。” 我不明白发生了什么。
    • @MuhammadAshikuzzaman 听起来你需要Ask a new question。请务必包含所有详细信息!
    • FirstOrDefault() 总是返回空值。我让它与pg.Key 一起工作,这实际上更有意义。我不明白FirstOrDefault 将如何返回任何对象,而我的分组依据是someId
    • @SZT 一旦你完成了group,你最终得到的东西(pg 这里)就是IGrouping。当您使用任何在IGrouping 上执行枚举类型的方法时,您正在迭代的是该组的成员。所以pg.FirstOrDefault() 是特定SomeId 组中Products 中的第一个(按任意顺序)。
    【解决方案2】:

    我们是这样做的:

    from p in Products                         
    join bp in BaseProducts on p.BaseProductId equals bp.Id                    
    where !string.IsNullOrEmpty(p.SomeId) && p.LastPublished >= lastDate                         
    group new { p, bp } by new { p.SomeId } into pg    
    let firstproductgroup = pg.FirstOrDefault()
    let product = firstproductgroup.p
    let baseproduct = firstproductgroup.bp
    let minprice = pg.Min(m => m.p.Price)
    let maxprice = pg.Max(m => m.p.Price)
    select new ProductPriceMinMax
    {
    SomeId = product.SomeId,
    BaseProductName = baseproduct.Name,
    CountryCode = product.CountryCode,
    MinPrice = minprice, 
    MaxPrice = maxprice
    };
    

    编辑:我们使用了 AakashM 的版本,因为它有更好的性能

    【讨论】:

      【解决方案3】:

      我遇到了和你一样的问题。

      我将两个tables result 推入t1 对象和组t1

       from p in Products                         
        join bp in BaseProducts on p.BaseProductId equals bp.Id
        select new {
         p,
         bp
        } into t1
       group t1 by t1.p.SomeId into g
       select new ProductPriceMinMax { 
        SomeId = g.FirstOrDefault().p.SomeId, 
        CountryCode = g.FirstOrDefault().p.CountryCode, 
        MinPrice = g.Min(m => m.bp.Price), 
        MaxPrice = g.Max(m => m.bp.Price),
        BaseProductName = g.FirstOrDefault().bp.Name
      };
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多