Сложный запрос EntityFramework с несколькими таблицами и множеством взаимосвязей - PullRequest
1 голос
/ 16 мая 2011

Я потратил кучу времени, чтобы заставить Entity Framework делать то, что я хочу.Я пишу агрегатор каналов, чтобы я мог добавить несколько RSS-каналов в «FeedList», который сгруппирует все отдельные подкасты и упорядочит их по pubDate.

Классы (все, кроме FeedListFeed, имеют столбец идентификации с именем Id):

  1. Feed (Id - первичный ключ удостоверения, имеет свойство List Items)
  2. FeedItem (Id - первичный ключ удостоверения, как свойства int FeedId и Feed Feed)
  3. FeedList(FeedListName является строкой и свойством List Feeds)
  4. FeedListFeed (таблица привязок «многие ко многим», свойства FeedListId и FeedId)

Кажется, что эти отображения работают:*

Теперь я хочу получить последние 20 записей FeedListItem для Feeds в FeedList с учетом FeedListName.Я придумал это, но есть ли лучший способ сделать это?Будет ли запрос фактически расширять все элементы или он будет достаточно умен, чтобы делать это на стороне SQL?

var query =
    from fl in ctx.FeedLists.Include("Feeds").Include("FeedItems")
    from f in fl.Feeds
    from fi in f.Items
    where fl.FeedListName == id
    orderby fi.PubDate descending
    select fi;
List<FeedItem> items = query.Take(20).ToList();

Если я попытаюсь связать таблицы вручную, используя столбцы Id, я получу ошибку Invalid object name 'dbo.FeedListFeeds1'. Если бы я вынул списки, связывающие таблицы друг с другом, это помогло бы?Есть ли какое-то другое сопоставление, которое позволяет этой работе?

var query =
    from fl in ctx.FeedLists
    join flf in ctx.FeedListFeeds on fl.Id equals flf.FeedListId
    join fi in ctx.FeedItems on flf.FeedId equals fi.FeedId
    where fl.FeedListName == id
    orderby fi.PubDate descending
    select fi;

1 Ответ

2 голосов
/ 17 мая 2011

Удалите эту строку из вашего сопоставления ...

modelBuilder.Entity<FeedListFeed>()
            .HasKey(x => x.FeedId)
            .HasKey(x => x.FeedListId);

... потому что у нее есть 2 проблемы:

1) Если вы хотите составной ключ, вы не должны связывать HasKey но создайте ключ через анонимный тип:

modelBuilder.Entity<FeedListFeed>()
            .HasKey(x => new { x.FeedId, x.FeedListId });

2) (более важно) Эта строка позволяет EF рассматривать FeedListFeed как сущность, которой нет в вашей модели.В результате EF создает для него отдельную таблицу с именем FeedListFeeds1, поскольку FeedListFeeds зарезервировано в качестве имени таблицы в вашем отображении «многие ко многим» (.ToTable("FeedListFeeds")).Для сопоставления «многие ко многим» вам не нужно создавать класс для таблицы связывания.Таблица ссылок управляется EF изнутри.

Редактировать

Затем вы также можете полностью удалить класс FeedListFeed.

Длязапрос, который я бы попробовал тогда:

var query = from fi in ctx.FeedItems
            where fi.Feed.FeedLists.Any(fl => fl.FeedListName == id)
            orderby fi.PubDate descending
            select fi;

Я думаю, у вас есть все необходимые свойства навигации в классах модели, чтобы этот запрос был возможен.

...