Сложный запрос linq to entity - PullRequest
0 голосов
/ 02 января 2012

У меня есть модель EF с 3 таблицами, Artist, Movie и Movie_Artist_Job.Movie_Artist_Job - это просто таблица внешнего ключа:

MovieId,ArtistId,JobId.

Я пытаюсь получить следующие результаты:

ArtistName1, Movie1

ArtistName1, Movie2

Artistname2, Movie1

Artistname2, Movie3

и т. Д.

Сейчас я делаю это:

var query = (
    from items in _objEntities.Movie_Artist_Job
    where items.Artist.FulleName != string.Empty
    select items.Artist.FulleName).Distinct<string>();

List<ThumbItem> Items = new List<ThumbItem>();

foreach (string fullName in query)
{
    var matching = (
        from movie in _objEntities.Movie_Artist_Job
        where movie.Artist.FulleName == fullName
        select movie.Movie)
        .Distinct<Movie>();

    if (matching.Count() > 0)
    {
        foreach (Movie movies in matching)
        {
            if (movies != null && movies.IsDeleted == false)
            {
                new ThumbItem(fullName, movies.title);
            }
        }
    }
}

Это работает, но это занимает много времени ...

Есть какие-нибудь подсказки о том, как оптимизировать это?

Большое спасибо за вашу помощь.

Ответы [ 4 ]

2 голосов
/ 02 января 2012

Вы запрашиваете базу данных внутри цикла.Это приводит к N + 1 запросам.Попробуйте переписать ваш код следующим образом:

var query = (
    from items in _objEntities.Movie_Artist_Job
    where items.Artist.FulleName != string.Empty
    select items.Artist.FulleName)
    .Distinct();

var matching =
    from fullName in query
    from movie in _objEntities.Movie_Artist_Job
    where movie.Artist.FulleName == fullName
    where !movies.IsDeleted
    select new { movie.fullName, movie.title })
    .Distinct()
    .ToArray();

List<ThumbItem> Items = (
    from movie in matching
    select new ThumbItem(movie.fullName, movie.title))
    .ToList();
0 голосов
/ 02 января 2012

То, что вы пытаетесь сделать, называется «поворотом», вам следует взглянуть на Linq Extensions Library о том, как этого добиться в правильно построенной модели EF.

В качестве примечания, суть EF в том, чтобы иметь возможность писать свои запросы естественным образом, ориентированным на объект, то есть вам не нужно беспокоиться о таблице Movie_Artist_Job на стороне C # (Вызов Artist.Movies должен вернуть список фильмов для данного исполнителя)

0 голосов
/ 02 января 2012

Я пытался скопировать БД, которую вы упомянули: -

  1. Художники
  2. Фильмы
  3. Работа

и ядобавить один класс сущности thumbItem следующим образом;чтобы выбрать элементы для: -

internal class ThumbItem
{
    public string ArtistName { set; get; }
    public string MovieName { set; get; }
}

и я выполнил следующую функцию, чтобы получить запрошенный вами результат: -

MoviesEntities context = new MoviesEntities();

        var Thumbs = from artist in context.Artists
                     join job in context.Jobs on artist.ID equals job.ArtistID
                     join movie in context.Movies on job.MovieID equals movie.ID
                     select new ThumbItem()
                                {
                                    ArtistName = artist.Name,
                                    MovieName = movie.Name
                                };


        dataGridView1.DataSource = Thumbs;

он работал очень быстро и ничего не занимал,я думаю, что ваша проблема заключалась в том, что вы разделили сопоставление и создание элементов управления на другие этапы, отличные от выполнения оператора соединения с помощью select в entity;какое действие заняло много времени.

РЕДАКТИРОВАТЬ: -

Новый вопрос из комментария: - нужно ли количество фильмов на исполнителя по одному и тому же запросу?

просто добавьте этот кодпосле того, как перед тем, как он получит результат с обратной связью DB: -

var ListByArtist = Thumbs.ToList().GroupBy(l => l.ArtistName).Select(lg => new
                        {
                            Artist = lg.Key,
                            NumberOfMovies = lg.Count()
                        });
0 голосов
/ 02 января 2012

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

public class Movie_Artist_Job
{
    public int Id { get; set; }
    public Artist Artist { get; set; }
    public Movie Movie { get; set; }
}

Затем просто вызовите db.Movie_Artist_Job.ToList()

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