【问题标题】:Linq query with aggregates带有聚合的 Linq 查询
【发布时间】:2009-02-25 15:07:57
【问题描述】:

我想编写一个优雅的 linq 查询来处理以下 SAMPLE 对象模型:

    class Category
    {
        public string Name { get; set; }        
        public IList<Product> Products { get; set;}        
    }

    class Product
    {
        public string Title { get; set; }
        public IList<Photo> Photos { get; set; }
    }

    class Photo
    {
        public int Id { get; set; }
    }

我构造了以下查询来获取照片 ID:

    var query = from category in Factory.GetCategories()
                where category.Name == "Cameras"
                select (from product in category.Products
                        where product.Title == "Sony"
                        select (from photo in product.Photos
                                select photo.Id)
                               );

    var v = query.ToList();

目前查询没有正确投影,我必须为每个子选择添加一个 FirstOrDefault()!:

var query = from category in Factory.GetCategories()
                where category.Name == "Cameras"
                select (from product in category.Products
                        where product.Title == "Sony"
                        select (from photo in product.Photos
                                select photo.Id).FirstOrDefault()
                               ).FirstOrDefault();

var v = query.ToList();

有没有更好的方法来做到这一点?忽略我们不是在处理数据库并且 PK/FK 没有发挥作用的事实。

当我可以在 linq 查询中做同样的事情时,我真的想避免编写大的 for 循环:

foreach (var category in Factory.GetCategories())
            {
                if (category.Name == "Camera")
                {
                    foreach (var product in category.Products)
                    {
                        if (product.Title == "Sony")
                        {
                            foreach (var photo in product.Photos)
                            {
                                //get data
                                int id = photo.Id;
                            }
                        }
                    }
                }                
            }

实际实现比这个简单的对象模型更复杂。我想从这个简单的示例中获得基本概念,因此我将其应用到我的真实对象模型中。

干杯!

【问题讨论】:

    标签: c# linq linq-to-objects


    【解决方案1】:

    你只想要扁平化的 id 吗?

            var query = from category in Factory.GetCategories()
                        where category.Name == "Cameras"
                        from product in category.Products
                        where product.Title == "Sony"
                        from photo in product.Photos
                        select photo.Id;
    

    【讨论】:

    • 干杯马克,我认为你和约翰提供了相同的答案:)。比我一开始的时候要优雅得多。
    【解决方案2】:

    是的,您必须添加 FirstOrDefault,因为没有“照片 ID”之类的东西。每个相机可能有很多照片 - 你想要哪张?

    如果您只关心第一张照片,那很好 - 尽管多个“from”子句会让您的生活更轻松:

    var query = from category in Factory.GetCategories()
                where category.Name == "Cameras"
                from product in category.Products
                where product.Title == "Sony"
                select product.Photos.Select(photo => photo.Id)
                                     .FirstOrDefault();
    

    请注意,对于没有照片的产品,这将返回 0。这就是你想要的吗?

    如果您能更清楚自己的要求,我们将更有能力为您提供帮助。

    编辑:如果您只想要 any Sony Camera 的第一个 ID,请使用:

    var query = from category in Factory.GetCategories()
                where category.Name == "Cameras"
                from product in category.Products
                where product.Title == "Sony"
                from photo in product.Photos
                select photo.Id;
    var firstId = query.FirstOrDefault();
    

    【讨论】:

      【解决方案3】:

      与其他所有人的答案相同,但使用扩展方法调用而不是查询理解。 SelectMany 允许您“解包”子集合并在该级别继续查询。

      var query = Factory.GetCategories()
        .Where(category => category.Name == "Cameras")
        .SelectMany(category => category.Products)
        .Where(product => product.Title == "Sony")
        .SelectMany(product => product.Photos)
        .Select(photo => photo.Id);
      

      【讨论】:

        【解决方案4】:
                var ids = from category in Factory.Categories
                          where category.Name == "Cameras"
                          from product in category.Products
                          where product.Title == "Sony"
                          from photo in product.Photos
                          select photo.Id;
        

        返回所有照片的id,没有照片时可枚举为空。 如果你想要第一个,或者默认为 0 :

        var result = ids.FirstOrDefault();
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-09-14
          • 2019-07-22
          • 2020-11-23
          • 2023-03-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多