Различать и группировать одновременно в LINQ? - PullRequest
1 голос
/ 22 января 2011

Допустим, у меня есть следующие классы:

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

Любая помощь будет принята с благодарностью!

Ответы [ 2 ]

0 голосов
/ 05 мая 2011

Я только сталкивался с этим вопросом, изучая LINQ, но я не был удовлетворен тем, что вывод Джона соответствовал этому вопросу (извините, Джон).Следующий код возвращает список объектов с анонимной типизацией, которые лучше соответствуют структуре вашего вопроса:

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();

Кредит идет в основном Джону Скиту и отладчику Visual Studio;)

Я понимаю,что вы, вероятно, уже продвинулись, но, надеюсь, это может помочь кому-то еще, желающему изучать LINQ, как и я.

0 голосов
/ 22 января 2011

Нет, вы не можете сделать это на основе того, что вы сказали - потому что «Цвет» и «Размер» являются частью данных , а не частью модели . Они известны только во время выполнения, поэтому, если вы не используете динамическую типизацию, вы не сможете получить к ней доступ через 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) });
...