Реализуйте «соединение» с различными таблицами в Entity Framework - PullRequest
0 голосов
/ 10 декабря 2018

У меня есть три таблицы:

Материалы :

  1. ID
  2. Заголовок
  3. Содержание

Likes :

  1. ID
  2. MaterialID
  3. UserID
  4. IsLiked

Посетители :

  1. ID
  2. Идентификатор пользователя
  3. Идентификатор материала
  4. Дата
  5. ReadNow

Я хотел бы получить объект вроде:

  1. Заголовок
  2. Контент
  3. CountLikes
  4. CountVisitors

Я пытался сделать следующее:

from mat in ctx.materials
let visitors = mat.VisitorsCollection.Where(x=>x.ReadNow).Count()
let likes = mat.LikesCollection.Where(x=>x.IsLiked).Count()
let iliked = mat.LikesCollection.Where(x=>x.UserID == myID && x.IsLiked).Any()
select new {
   Material = mat,
   Visitors = visitors,
   Likes = likes,
   Liked = iliked
}

Я получаю подборку материалов и отдельно Entity Framework получает данные о количестве посетителей и т. Д.

Я также попробовал следующее:

from mat in ctx.materials
join lik in ctx.Likes.Where(x=>x.UserID == myID && x.IsLiked) on map.ID equals lik.MaterialID 
select new {
   Material = mat,
   Liked = lik.Any()
}

, но теперь происходит ошибка:

Microsoft.EntityFrameworkCore.Query: Предупреждение: выражение LINQ 'Any ()' не может бытьпереведен и будет оцениваться на месте.

Ответы [ 2 ]

0 голосов
/ 10 декабря 2018

Если вы используете Entity Framework, рассмотрите возможность использования ICollections вместо самостоятельного выполнения соединений.

У вас есть последовательность Materials, где каждый Material имеет ноль или более Likes иноль или более Visitors, оба отношения один-ко-многим, с использованием внешнего ключа для Material.

Если вы выполнили первые соглашения кода структуры сущности , вы 'Классы, подобные следующим:

class Material
{
     public int Id {get; set;}
     public string Title {get; set;}
     public string Content {get; set;}

     // every Material has zero or more Likes (one-to-many)
     public virtual ICollection<Like> Likes {get; set;}

     // every Material has zero or more Visitors (one-to-many)
     public virtual ICollection<Visitor> Visitors {get; set;}
}

Likes and Посетители:

class Like
{
     public int Id {get; set;}
     public bool IsLiked {get; set;}
     ...

     // every Like belongs to exactly one Material, using foreign key
     public int MaterialId {get; set;}
     public virtual Material Material {get; set;}
}

class Visitor
{
     public int Id {get; set;}
     ...

     // every Visitor belongs to exactly one Material, using foreign key
     public int MaterialId {get; set;}
     public virtual Material Material {get; set;}
}

Это все, что необходимо для определения структуры отношения один-ко-многим.Возможно, вам нужны разные имена таблиц или разные идентификаторы для ваших столбцов.В этом случае требуются атрибуты или свободный API

В структуре сущностей столбцы таблиц представлены не виртуальными свойствами.Виртуальные свойства представляют отношения между таблицами (один-ко-многим, многие-ко-многим и т. Д.)

Как только вы правильно определили определения классов, ваш запрос прост и очень интуитивен:

Требование:

Из моей коллекции Материалов, дайте мне от каждого Материала, Названия, Контента, количества Лайков и количества Посетителей:

var result = myDbContext.Materials
   .Where(material => ...)            // only if you don't want all Materials
   .Select(material => new            // from every Material make one new object
   {                                  // containing the following properties
       Title = material.Title,
       Content = material.Content,

       // if you want any information of the likes of this material, use property Likes
       LikeCount = material.Likes
           .Where(like => like.IsLiked)  // optional, only if you don't want all likes
           .Count(),
       NrOfVisitors = material.Visitors
           .Where(visitor => ...)        // only if you don't want all visitors
           .Count(),
   });

Словами: из моей полной коллекции Материалов оставьте только те Материалы, которые ... Из каждого оставшегося Материала создайте один новый объект:

  • Заголовокявляется названием материала
  • Содержимое является содержимым материала
  • LikeCount - это число Лайков этого материала (которые имеют истинный IsLiked)
  • NrOfVisitors - этоколичество посетителей этого материала (то есть ...)

Entity Framework знает ваши отношения и знает, что нужен GroupJoin.

0 голосов
/ 10 декабря 2018

Хорошо, если у вас есть внешние ключи в базе данных, тогда EF сгенерирует связи между объектами, поэтому все, что вам нужно сделать, это:

var result = ctx.materials.Select(x => 
     new SomeClass{
          Material = x,
          Visitors = x.Visitors.Where(v => v.ReadNow).Count(),
          Likes = x.Likes.Where(y => y.IsLiked).Count(),
          Liked = x.Likes.Where(z => z.IsLiked && z.UserID == myID).Count()
     }).ToList();

Возможно, синтаксис не совсем правильный, но вы получитеточка ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...