Поиск на основе отношения «многие ко многим»
Говоря о статьях и авторах, когда в каждой статье может быть много авторов, предположим, что вы собираетесь искать по term
и найти Статьи, где название статьи или реферат статьи содержат термин, или один из авторов статьи имеет термин в своем имени или фамилии.
EF 6 - Many-To- Может без класса сущности для Отношения
Вы можете обрабатывать эти случаи в запросе Linq, используя Any
, так же, как вы можете обрабатывать в запросе SQL, используя EXISTS
:
Where(article=> article.Title.Contains(term) ||
article.Abstract.Contains(term) ||
article.Authors.Any(author =>
author.FirstName.Contains(term) ||
author.LastName.Contains(searchTerm)))
Он точно не генерирует следующий SQL Запрос, но логика c очень похожа на следующее в SQL:
FROM Articles
WHERE (Articles.Title LIKE '%' + @Term + '%') OR
(Articles.Abstract LIKE '%' + @Term + '%') OR
EXISTS (SELECT * FROM Authors
WHERE (Authors.FirstName LIKE '%' + @Term + '%') OR
(Authors.LastName LIKE '%' + @Term + '%'))
EF CORE - многие-на-май с классом сущностей для отношений
На данный момент отношения многие-ко-многим без класса сущностей для представления таблицы соединений еще не поддерживаются.
Вы можете обрабатывать эти случаи в запросе Linq, используя Any
, так же, как вы можете обрабатывать в запросе SQL, используя EXISTS
+ Join
:
.Where(article => article.Title.Contains(model.SearchTerm) ||
article.Abstract.Contains(model.SearchTerm) ||
article.ArticlesAuthors.Any(au =>
(au.Author.FirstName).Contains(model.SearchTerm) ||
(au.Author.LastName).Contains(model.SearchTerm)))
Это не совсем генерирует следующий SQL Запрос, но логика c очень похожа на следующее в SQL:
FROM Articles
WHERE (Articles.Title LIKE '%' + @Term + '%') OR
(Articles.Abstract LIKE '%' + @Term + '%') OR
EXISTS (SELECT * FROM ArticlesAuthors
INNER JOIN Authors
ON ArticlesAuthors.AuthorId = Authors.Id
WHERE ((Authors.FirstName LIKE '%' + @Term + '%') OR
(Authors.LastName LIKE '%'+ @Term + '%')) AND
(Articles.Id = ArticlesAuthors.ArticleId))
EF 6 - Пример
Вопрос немного запутан, включая сортировку поиска и много кода, и требует большего внимания. Чтобы сделать его более полезным и понятным для вас и читателей функций, я буду использовать более простую модель с меньшим количеством свойств и более легкой для понимания.
Как видно на диаграмме EF, таблица ArticlesAuthors
имеет не показаны на диаграмме, потому что это отношение «многие ко многим», содержащее только столбцы Id других сущностей без каких-либо дополнительных полей
Логики поиска c
Мы хотим найти статьи на основе SerachTerm
, PublishDateFrom
и PublishDateTo
:
- Если заголовок или реферат статьи содержит термин, статья должна быть часть результата.
- Если комбинация имени и фамилии автора статьи содержит термин, статья должна быть частью результата.
- Если дата публикации sh больше или равна
PublishDateFrom
, статья должна быть частью результата, также если дата публикации sh меньше или равна PublishDateTo
, статья должно быть частью результата.
Вот модель для поиска:
public class ArticlesSearchModel
{
public string SearchTerm { get; set; }
public DateTime? PublishDateFrom { get; set; }
public DateTime? PublishDateTo { get; set; }
}
Вот код для поиска:
Обратите внимание : Inculde
не имеет ничего общего с поиском, а просто для включения связанных сущностей в выходной результат.
public class ArticlesBusinessLogic
{
public IEnumerable<Article> Search(ArticlesSearchModel model)
{
using (var db = new ArticlesDBEntities())
{
var result = db.Articles.Include(x => x.Authors).AsQueryable();
if (model == null)
return result.ToList();
if (!string.IsNullOrEmpty(model.SearchTerm))
result = result.Where(article => (
article.Title.Contains(model.SearchTerm) ||
article.Abstract.Contains(model.SearchTerm) ||
article.Authors.Any(author =>
(author.FirstName + " " + author.LastName).Contains(model.SearchTerm))
));
if (model.PublishDateFrom.HasValue)
result = result.Where(x => x.PublishDate >= model.PublishDateFrom);
if (model.PublishDateFrom.HasValue)
result = result.Where(x => x.PublishDate <= model.PublishDateTo);
return result.ToList();
}
}
}
EF CORE - Пример
Как я Как уже упоминалось выше, на данный момент отношения «многие ко многим» без класса сущности для представления таблицы объединения еще не поддерживаются, поэтому модель, использующая EF CORE, будет иметь вид:
Вот код для поиска:
Обратите внимание: Inculde
не имеет ничего общего с поиском, он просто для включения связанных сущностей в выходной результат .
public IEnumerable<Article> Search(ArticlesSearchModel model)
{
using (var db = new ArticlesDbContext())
{
var result = db.Articles.Include(x=>x.ArticleAuthor)
.ThenInclude(x=>x.Author)
.AsQueryable();
if (model == null)
return result;
if (!string.IsNullOrEmpty(model.SearchTerm))
{
result = result.Where(article => (
article.Title.Contains(model.SearchTerm) ||
article.Abstract.Contains(model.SearchTerm) ||
article.ArticleAuthor.Any(au =>
(au.Author.FirstName + " " + au.Author.LastName)
.Contains(model.SearchTerm))
));
}
if (model.PublishDateFrom.HasValue)
{
result = result.Where(x => x.PublishDate >= model.PublishDateFrom);
}
if (model.PublishDateFrom.HasValue)
{
result = result.Where(x => x.PublishDate <= model.PublishDateTo);
}
return result.ToList();
}
}