@ccc35

Как написать LINQ запрос?

В базе данных есть поле Актёры. Имена и фамилии актёров записаны через запятую. Необходимо при запросе вылавливать все точные совпадения имен либо фамилий.

Есть три варианта
if (!string.IsNullOrEmpty(movieActors))
            {
                //1. movies = movies.Where(x => x.Actors.Contains(movieActors));
                //2. movies = movies.Where(x => arr.Contains(movieActors));
                //3. movies = movies.Where(x => x.Actors.Split(' ').Contains(movieActors));    
            }

Первый работает, но не хорошо. Выдает любое совпадение символов.
Во втором варианте в цикле перебирал все строки из базы и разделял имена и фамилии сохраняя в массиве arr. Запрос не работает.
Третий выдает ошибку - что-то с приведением типов.

Подскажите как написать запрос ?
  • Вопрос задан
  • 632 просмотра
Пригласить эксперта
Ответы на вопрос 4
adminstock
@adminstock
★ Решения для Debian ★
Если имена через запятую, то разбивать нужно по запятой:
movies.Where(x => x.Actors.Split(',').Contains(movieActors));

С проверкой на пустоту:
movies.Where(x => !String.IsNullOrEmpty(x.Actors) && x.Actors.Split(',').Contains(movieActors));


Альтернативный вариант:
movies.Where
(
  x => 
  !String.IsNullOrEmpty(x.Actors) &&
  x.Actors.Split(',').Any((actor) => actor.Equals(movieActors))
);

Еще один:
movies.Where(x => !String.IsNullOrEmpty(x.Actors) && x.Actors.Split(',').IndexOf(movieActors) != -1);


Если имена содержат пробелы, еще более ресурсоемкий запрос с удалением пробелов будет примерно таким:
movies.Where
(
  x => 
  !String.IsNullOrEmpty(x.Actors) && 
  x.Actors.Split(',').Select(a => a.Trim()).Any((actor) => actor.Equals(movieActors))
);


При ошибке: does not recognize the method 'System.String[] Split(Char[])'
вероятно придется получить данные (в массив):
movies.ToList().Where
(
  x => 
  !String.IsNullOrEmpty(x.Actors) && 
  x.Actors.Split(',').Select(a => a.Trim()).Any((actor) => actor.Equals(movieActors))
);

Плохое решение, лучше структуру данных поменять, хранить актеров в нормальном виде, чтобы не приходилось их разбивать на массивы. Вариант поиска подстроки наиболее хорош в плане производительности:
movies = movies.Where(x => x.Actors.Contains(movieActors));
Ответ написан
Комментировать
@ccc35 Автор вопроса
Спасибо за помощь, но во всех случаях выходит ошибка при поиске. Ошибка такая же как и моём третьем варианте.
LINQ to Entities does not recognize the method 'System.String[] Split(Char[])' method, and this method cannot be translated into a store expression.

Возникает при возврате значения
return View(movies.ToList().ToPagedList(pageNumber, pageSize));

Вот сам метод
public ActionResult Index(string movieTitle, string movieGenre, string movieActors, int? page)
        {
            int pageSize = 10; int pageNumber = (page ?? 1); //Настройки постраничной навигации (кол-во страниц/страница по умолчанию)

            var movies = from m in db.FilmsTables
                         select m;

            if (!string.IsNullOrEmpty(movieActors))
            {
                //movies = movies.Where(x => x.Actors.Contains(movieActors));
                //movies = movies.Where(x => arr.Contains(movieActors));
                //movies = movies.Where(x => x.Actors.Split(' ').Contains(movieActors));    

                movies = movies.Where
                (
                  x =>
                  !String.IsNullOrEmpty(x.Actors) &&
                  x.Actors.Split(',').Select(a => a.Trim()).Any((actor) => actor.Equals(movieActors))
                );
            }

            return View(movies.ToList().ToPagedList(pageNumber, pageSize));
        }
Ответ написан
Комментировать
Плохо как то.
Сравнивать строки надо без учета регистра, что бы "Иван" был равен "ИВАН".

Строка получается в базе такого типа:
"Иванов Иван, Петров, Сидоров С., П.Д. Сергеев ... "

Вспоминаю что не хорошо хранить данные в SQL через запятую, переведите их в другую таблицу и сделайте миграцию.

Сейчас проблема найти, потом проблема изменить фамилию, потом нужно будет добавить какие то данные, разбить их на группы и т.д.
Один актер может играть в нескольких фильмах, и сейчас хранится копиями в каждой сущности, легко будет изменить его имя, думаю что нет.
Нужна связь многие ко многим. И тогда вы сможете находить всех актеров по фильму, и все фильмы по актеру.

Ошибка возникает в методе ToList() потому что именно он и делает отложенный запрос, который выше в коде был только сконфигурирован но не выполнен.

Для быстрого решения проблемы здесь и сейчас есть решение на SA -> LINQ to Entities does not recognize the method 'Sy...
Ответ написан
Комментировать
Выше писали - создайте список актеров.
Если имена разделены запятыми
то три проверки
actor == value
or
actor.contains("," + value + "," (may be comparision ignore case))
or
actor .endwiths("," + value)

с учетом пробелом.

посмотрел ссылку,
там есть этот вариант
stackoverflow.com/questions/23929801/linq-to-entit...
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы