在 LINQ 中同时区分和分组?

发布于 2024-10-13 08:03:53 字数 1076 浏览 10 评论 0原文

假设我有以下类:

Product { ID, Name }

Meta { ID, Object, Key, Value }

Category { ID, Name }

Relation {ID, ChildID, ParentID } (Child = Product, Parent = Category)

和一些示例数据:

产品:

ID   Name

1    Chair
2    Table

ID   Object  Key     Value

1      1     Color   "Red"
2      1     Size    "Large"
3      2     Color   "Blue"
4      2     Size    "Small"

类别

ID   Name

1    Indoor
2    Outdoor

关系

ID   ChildID   ParentID

1       1         1
2       1         2
3       2         1

我们可以使用 Distinct 和 Group by 来生成以下格式(ProductDetail)

ID=1,
Name=Chair,
Parent=
{
  { ID=1, Name="Indoor" },
  { ID=2, Name="Outdoor" }
},
Properties { Color="Red", Size="Large" }

ID=2,
Name=Table,
Parent=
{
  { ID=1, Name="Indoor"}
},
Properties { Color = "Blue", Size = "Small" }

获取第一个项目的“颜色”值

ProductDetails[0].Properties.Color

,我们可以使用Any 帮助 将不胜感激!

Let say I have the following classes:

Product { ID, Name }

Meta { ID, Object, Key, Value }

Category { ID, Name }

Relation {ID, ChildID, ParentID } (Child = Product, Parent = Category)

and some sample data:

Product:

ID   Name

1    Chair
2    Table

Meta

ID   Object  Key     Value

1      1     Color   "Red"
2      1     Size    "Large"
3      2     Color   "Blue"
4      2     Size    "Small"

Category

ID   Name

1    Indoor
2    Outdoor

Relation

ID   ChildID   ParentID

1       1         1
2       1         2
3       2         1

Can we use Distinct and Group by to produce the following format (ProductDetail)

ID=1,
Name=Chair,
Parent=
{
  { ID=1, Name="Indoor" },
  { ID=2, Name="Outdoor" }
},
Properties { Color="Red", Size="Large" }

ID=2,
Name=Table,
Parent=
{
  { ID=1, Name="Indoor"}
},
Properties { Color = "Blue", Size = "Small" }

which we can get the "Color" value of the first item by using

ProductDetails[0].Properties.Color

Any helps would be appreciated!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

浪漫人生路 2024-10-20 08:03:53

不,您不能根据您所说的进行操作 - 因为“颜色”和“尺寸”是数据的一部分,而不是模型的一部分。它们仅在执行时已知,因此除非您使用动态类型,否则您将无法通过 Properties.Color 访问它。

但是,您可以使用 Properties["Color"]

var query = from product in db.Products
            join meta in db.Meta 
                on product.ID equals meta.Object 
                into properties
            select new { Product = product,
                         Properties = properties.ToDictionary(m => m.Key,
                                                              m => m.Value) };

因此,对于每个产品,您将拥有一个属性字典。这在逻辑上是有效的,但您可能需要调整它才能使其在实体框架中工作 - 我不知道它对 ToDictionary 的支持有多好。

编辑:好的,我将保留上述内容作为“理想”解决方案,但如果 EF 不支持 ToDictionary,则必须在进程中执行该部分:

var query = (from product in db.Products
             join meta in db.Meta 
                 on product.ID equals meta.Object 
                 into properties
             select new { product, properties })
            .AsEnumerable()
            .Select(p => new {
                    Product = p.product,
                    Properties = p.properties.ToDictionary(m => m.Key,
                                                           m => m.Value) });

No, you can't do this based on what you've said - because "Color" and "Size" are part of the data, rather than part of the model. They're only known at execution time, so unless you use dynamic typing, you're not going to be able to access it by Properties.Color.

You could, however, use Properties["Color"] potentially:

var query = from product in db.Products
            join meta in db.Meta 
                on product.ID equals meta.Object 
                into properties
            select new { Product = product,
                         Properties = properties.ToDictionary(m => m.Key,
                                                              m => m.Value) };

So for each product, you'll have a dictionary of properties. That works logically, but you may need to tweak it to get it to work in the entity framework - I don't know how well that supports ToDictionary.

EDIT: Okay, I'll leave the above up as the "ideal" solution, but if EF doesn't support ToDictionary, you'd have to do that part in-process:

var query = (from product in db.Products
             join meta in db.Meta 
                 on product.ID equals meta.Object 
                 into properties
             select new { product, properties })
            .AsEnumerable()
            .Select(p => new {
                    Product = p.product,
                    Properties = p.properties.ToDictionary(m => m.Key,
                                                           m => m.Value) });
Saygoodbye 2024-10-20 08:03:53

我刚刚在学习 LINQ 时遇到了这个问题,但我对 Jon 的输出与问题相匹配不满意(对不起 Jon)。以下代码返回一个更好地匹配您的问题结构的匿名类型对象列表:

var ProductDetails = (from p in Product
                      let Parents = from r in Relation
                                    where r.ChildID == p.ID
                                    join c in Category on r.ParentID equals c.ID
                                        into RelationCategory
                                    from rc in RelationCategory
                                    select new
                                    {
                                        rc.ID,
                                        rc.Name
                                    }
                      join m in Meta on p.ID equals m.Object into ProductMeta

                      select new
                      {
                          p.ID,
                          p.Name,
                          Parent = Parents.ToList(),
                          ProductMeta
                      })
                     .AsEnumerable()
                     .Select(p => new
                     {
                         p.ID,
                         p.Name,
                         p.Parent,
                         Properties = p.ProductMeta
                                       .ToDictionary(e => e.Key, e => e.Value)
                     }).ToList();

主要归功于 Jon Skeet 和 Visual Studio 调试器;)

我意识到您现在可能已经继续前进,但希望这可能对某人有所帮助其他人也像我一样想学习 LINQ。

I just came across this question while learning LINQ, but I wasn't satisfied that Jon's output matched the question (sorry Jon). The following code returns a List of anonymously-typed objects that better match the structure of your question:

var ProductDetails = (from p in Product
                      let Parents = from r in Relation
                                    where r.ChildID == p.ID
                                    join c in Category on r.ParentID equals c.ID
                                        into RelationCategory
                                    from rc in RelationCategory
                                    select new
                                    {
                                        rc.ID,
                                        rc.Name
                                    }
                      join m in Meta on p.ID equals m.Object into ProductMeta

                      select new
                      {
                          p.ID,
                          p.Name,
                          Parent = Parents.ToList(),
                          ProductMeta
                      })
                     .AsEnumerable()
                     .Select(p => new
                     {
                         p.ID,
                         p.Name,
                         p.Parent,
                         Properties = p.ProductMeta
                                       .ToDictionary(e => e.Key, e => e.Value)
                     }).ToList();

Credit goes mostly to Jon Skeet and the Visual Studio debugger ;)

I realise that you've probably moved on by now but hopefully this might help someone else looking to learn LINQ, as I was.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文