Linq 按连接表中的项目计数分组

Posted

技术标签:

【中文标题】Linq 按连接表中的项目计数分组【英文标题】:Linq grouping by item count from joined table 【发布时间】:2021-10-13 13:59:42 【问题描述】:

我浏览了一堆答案,并试图让代码正常工作,但看不到按 _productBundlesItemsRepository 表分组的方法

这是我正在查看的查询

return _productBundlesRepository.Table.Join(_productBundleItemsRepository.Table,
                    pbr => pbr.Id,
                    pbir => pbir.BundleId,
                    (pbr, pbir) => new  Bundle = pbr, BundleItem = pbir)
                .Where(x => x.BundleItem.ProductId == productId && x.BundleItem.Visible == true && x.Bundle.Active == true).Select(x => x.Bundle).ToList();

我想也许我可以做这样的事情 .OrderByDescending(x => x.BundleItem.Count()) 但该选项不可用

我还尝试了一些方法,比如在这样的新语句中获取链接到捆绑包的项目数

new  Bundle = pbr, BundleItem = pbir, Count = GetProductBundleItems(pbr.Id).Count)

然后我收到这样的错误

System.NotSupportedException:LINQ to Entities 无法识别方法“System.Collections.Generic.List”

我不太确定如何订购由捆绑包中包含的捆绑包项目数量返回的捆绑包。

更新我根据@StriplingWarrior 的回答使用了一些修改过的代码,但似乎这不起作用,因为多个捆绑包可以包含相同的项目。 即一个捆绑包是 2 包,另一个捆绑包是 4 包,两者都使用相同的物品。 这是我更新的代码

var bundleItems = _productBundleItemsRepository.Table
                .Where(bundleItem => bundleItem.ProductId == productId
                                     && bundleItem.Visible == true);
            return _productBundlesRepository.Table
                .Select(bundle => new BundleWithCount  pb = bundle, count = bundleItems.Count(bundleItem => bundleItem.BundleId == bundle.Id) )
                .Where(x => x.pb.Active == true && x.count > 0).OrderByDescending(x => x.count).Select(x => x.pb)
                .ToList();

internal class BundleWithCount
    
        public int count  get; set; 

        public ProductBundle pb  get; set; 
    

有人知道我哪里出错了吗?

谢谢

【问题讨论】:

“多个捆绑包可以包含同一个项目”是什么意思?如果一个 BundleItem 有一个 BundleId,这是否意味着关系是多对一的?即使没有,您也需要澄清什么“行不通”?你有错误吗?结果与您的预期不同?需要更多详细信息。 我明白了@StriplingWarrior 谢谢:) 【参考方案1】:

当您不想从两个表中获取标量数据时,联接并不是很好。像这样的东西对于仅获取捆绑包会更有效。

return _productBundlesRepository.Table
    .Where(bundle => bundle.Active == true
        && _productBundleItemsRepository.Table
            .Any(bundleItem => bundleItem.BundleId == bundle.Id
                 && bundleItem.ProductId == productId 
                 && bundleItem.Visible == true))
    .ToList();

或者,换一种说法:

var bundleItems = _productBundleItemsRepository.Table
    .Where(bundleItem => bundleItem.ProductId == productId 
        && bundleItem.Visible == true);
return _productBundlesRepository.Table
    .Where(bundle => bundle.Active == true
        && bundleItems.Any(bundleItem => bundleItem.BundleId == bundle.Id))
    .ToList();

然后,如果您想要每个捆绑包的捆绑商品数量:

var bundleItems = _productBundleItemsRepository.Table
    .Where(bundleItem => bundleItem.ProductId == productId 
        && bundleItem.Visible == true);
return _productBundlesRepository.Table
    .Select(bundle => new BundleWithCount bundle, count=bundleItems.Count(bundleItem => bundleItem.BundleId == bundle.Id))
    .Where(x => x.bundle.Active == true && x.count > 0)
    .ToList();

(您需要定义BundleWithCount 类,以便您可以返回基于该类型对象的泛型)

【讨论】:

嘿,谢谢帮助,这个 new BundleWithCount bundle 包说“无效的初始化程序成员声明器” 嗨 StriplingWarrior 我得到了代码工作但有一个问题,请查看我在问题中的更新。谢谢【参考方案2】:

我设法解决了这个问题,首先订购的商品数量然后是商品数量。就像我计划的那样。感谢@StriplingWarrior 为我指明了正确的方向:)

public List<ProductBundle> GetBundlesActive()
        
            var bundleItems = _productBundleItemsRepository.Table
                .Where(bundleItem => bundleItem.Visible == true);
            var bundleItemCount = _productBundleItemsRepository.Table
                .Where(bundleItem => bundleItem.Visible == true);
            return _productBundlesRepository.Table
                .Select(bundle => new BundleWithCount  Pb = bundle, Count = bundleItems.Count(bundleItem => bundleItem.BundleId == bundle.Id), ItemCount = bundleItemCount.FirstOrDefault(bundleItem => bundleItem.BundleId == bundle.Id).Quantity )
                .Where(x => x.Pb.Active == true && x.Count > 0).OrderByDescending(x => x.Count).ThenByDescending(x => x.ItemCount).Select(x => x.Pb)
                .ToList();
        

以及这个的内部类

internal class BundleWithCount
    
        public int Count  get; set; 

        public int ItemCount  get; set; 

        public ProductBundle Pb  get; set; 
    

【讨论】:

以上是关于Linq 按连接表中的项目计数分组的主要内容,如果未能解决你的问题,请参考以下文章

Linq 选择新对象

Rails:按用户分组项目,然后计数状态

LINQ,按属性分组,同时保持其他属性排序

LINQ的求和 平均 最大 最小 分组 计数 等等

如何将 LINQ 左外连接限制为一行

Linq,EF Core - 按一个字段分组并使用其他字段从其他表中获取数据列表