Получите детали, соединяя таблицы с группой по условию в Linq и EF

У меня есть следующие 3 определения таблиц в моей базе данных SQL Server:

+----------------------------------+-----------------+------------------------------------------------
|             Product              | Rating                          |         Image                   | 
+----------------------------------+-----------------+-------------------------------------------------
| ProductId                        | Id                              | Id                              |
| ProdctName                       | Rating                          | Image                           |
|                                  | ProductId FK References(Product)| ProductId FK References(Product)|
+----------------------------------+-----------------+---------------+----------------------------------

И эти таблицы содержат следующие примеры данных:

+----------------------------------+------------
|Product              | ProductId  |ProductName |
+----------------------------------+------------
|                     | 1          |Prodcuct 1  |
|                     | 2          |Prodcuct 2  |
|                     | 3          |Prodcuct 3  |
|                     | 4          |Prodcuct 4  |
+----------------------------------+------------+

+----------------------------------+----------------------+
|Rating              | Id          |RatingVal   |ProductId |
|+----------------------------------+-----------------------
|                     | 1          |3           |1         |
|                     | 2          |2           |2         | 
|                     | 3          |3           |2         |
|                     | 4          |5           |3         |
|                     | 5          |4           |3         |
+---------------------+------------+------------+----------+

+----------------------------------+----------------------+
|Image                | Id          |ImagePath  |ProductId
+----------------------------------+-----------------------
|                     | 1          |ABC           |1       |
|                     | 2          |XYZ           |2       | 
|                     | 3          |LMN           |3       |
|                     | 4          |PQR           |4       |
+---------------------+------------+------------+----------+

Мне нужно собрать информацию о + ---------------------------------- + ------- ------------------------- + | Выход | ProductId | ProductName | Avg ( Рейтинг ) | ImgPath | + ---------------------------------- + -------------- ------------------ + | | 1 | Prodcuct 1 | 3 | ABC | | | 2 | Prodcuct 2 | 2,5 | XYZ | | | 3 | Prodcuct 3 | 4.5 | LMN | | | 4 | Prodcuct 4 | 0.0 | PQR | + ---------------------------------- + ------------ + - ---------- + ------- + в одном месте, так что каждый вар trendingProducts = ( от оценок в сущности . Рейтинг группы оценок по новым { оценок . PRODUCTID } в с присоединиться продукты в юридические лица . продукты на с . FirstOrDefault (). ProductID равно продукцией . PRODUCTID присоединиться изображениями в лицах . изображения на с . ключом . PRODUCTID равно изображений . PRODUCTID выбрать новый ProductViewModel { ProductID = продукты . PRODUCTID , ProductName = продукты . ProductName , RatingVal = с . Средний ( л => л . RatingVal ) == NULL ? 0 : гр . Средняя ( л => л . Оценка ), путь_к_образ = изображения . путь_к_образ , }). ToList (); содержит информацию о продуктах (из таблицы рейтингов), соответствующие средние изображения (из таблицы продуктов) m и рейтинг для рейтинга (из таблицы продуктов). Другими словами, мне нужен следующий вывод:

ProductId

Я использую Entity Framework для извлечения этих данных и объектов в классе контекста в моем коде (показано ниже).

Мой вопрос: как я могу получить желаемый результат для всех продуктов. Мой код ниже не может получить все данные, которые я хочу. Проблема в том, что продукт с id4 не отображается в результате, я предполагаю, что это связано с тем, что продукт 4 не имеет записи в таблице Product.

Images

c#,sql-server,entity-framework,linq,

0

Ответов: 1


0 принят

Итак, у вас есть таблица Products, таблица Ratingsи стол Image.

Каждый из них Productимеет ноль или более Ratings, каждый из них Ratingпринадлежит только одному, Productиспользуя внешний ключ Image. Точно так же каждый Productимеет ноль или более ProductId, каждый из них Productпринадлежит точно одному Image, используя внешний ключ Images. Просто стандартные отношения «один ко многим».

Может быть, каждый Productимеет нуль-один Image: в этом случае у вас есть отношение «нуль-один-к-одному». Код будет аналогичным. Главное отличие состоит в том, что «Продукт» не будет иметь набор Image, он будет иметь только один виртуальный Image.

Если вы будете следовать первым правилам кода рамки сущности, у вас будут такие классы, как:

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

    // every Product has zero or more Ratings:
    public virtual ICollection<Rating> Ratings {get; set;}

    // every product has zero or more Images:
    public virtual ICollection<Image> Images {get; set;}

    ... // other properties
}

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

    // every Rating belongs to exactly one Product using foreign key:
    public int ProductId {get; set;}
    public virtual Product Product {get; set;} 

    ...
}

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

    // every Image belongs to exactly one Product using foreign key:
    public int ProductId {get; set;}
    public virtual Product Product {get; set;} 

    ...
}

Это все, что должна знать структура сущности, чтобы обнаружить ваши отношения «один ко многим». Он знает, какие таблицы / столбцы вам нужны, и он знает отношения между таблицами. Возможно, вам нужны разные идентификаторы для ваших таблиц или свойств. В этом случае вам понадобятся атрибуты или свободный API. Но это выходит за рамки этого вопроса.

Обратите внимание, что в инфраструктуре сущности все не виртуальные свойства станут столбцами в ваших таблицах. Все виртуальные свойства представляют собой отношения между таблицами.

Мне нужно собрать информацию о продукте в одном месте, чтобы каждый продукт содержал информацию о продукте (из таблицы продуктов), соответствующий средний рейтинг (из таблицы оценок) и путь изображения для продукта (из таблицы изображений).

Всякий раз, когда люди запрашивают «объекты со своим под-объектом», они стремятся создать (групповое) соединение. Однако, если вы используете структуру сущностей, гораздо проще использовать ICollectionsдля этих запросов. Если вы используете ICollection, Entity Framework будет знать, что требуется объединение (группа).

var result = myDbContext.Products            // from the collection of Products
    .Where(product => ...)                   // select only those Products that ...
    .Select(product => new                   // from every remaining Product make one new
    {                                        // object with the following properties:
         // Select only the properties you actually plan to use!
         Id = product.Id,
         Name = product.ProductName,
         ...

         AverageRating = product.Ratings       // from all Ratings of this Product
             .Select(rating => rating.Rating)  // get the Rating value
             .Average(),                       // and Average it.

         Images = product.Images               // from all Images of this product
             .Select(image => image.ImagePath) // select the ImagePath
             .ToList(),

         // or if a Product has only zero or one Image:
         Image = product.Image?.ImagePath // if the product has an Image, get its ImagePath
                                          // or use null if there is no Image
    });

Самое приятное в использовании ICollections - то, что код является более простым и более естественным, он выглядит более похожим на текст вашего требования, чем объединение (group). Кроме того, если задействовано более двух таблиц (групп), похоже, они выглядят ужасно.

Я не буду пытаться дать решение, используя GroupJoin. Я уверен, что другие ответы покажут это. Сравните и убедитесь сами, какое решение кажется более понятным.

C #, SQL-сервер, сущность-рамка, LINQ,
Похожие вопросы
Яндекс.Метрика