具有多个表和多对多关系的复杂实体框架查询

本文关键字:复杂 实体 框架 查询 关系 | 更新日期: 2023-09-27 17:56:30

我花了很长时间让实体框架做我想做的事。 我正在编写一个提要聚合器,以便我可以将多个 rss 提要添加到"FeedList"中,该提要将对所有单独的播客进行分组并按 pubDate 排序。

类(除了 FeedListFeed 之外,所有类都有名为 Id 的标识列):

  1. 源(Id 是标识主键,具有"列表项"属性)
  2. FeedItem (Id 是标识主键,作为 int FeedId 和 Feed Feed 属性)
  3. 源列表(源列表
  4. 名称是字符串和列表源属性)
  5. FeedListFeed
  6. (多对多链接表、FeedListId 和 FeedId 属性)

这些映射似乎有效:

modelBuilder.Entity<FeedListFeed>().HasKey(x => x.FeedId).HasKey(x => x.FeedListId);
modelBuilder.Entity<FeedList>()
.HasMany(fl => fl.Feeds).WithMany(f => f.FeedLists)
.Map(t => t.MapLeftKey("FeedListId")
.MapRightKey("FeedId")
.ToTable("FeedListFeeds"));

现在我想做的是在给定 FeedListName 的情况下获取 FeedList 中源的最新 20 个 FeedListItem 条目。 我已经想出了这个,但是有更好的方法吗? 查询是否真的会扩展所有项目,或者它是否足够智能,可以在 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;

具有多个表和多对多关系的复杂实体框架查询

从映射中删除此行...

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;

我认为您的模型类中具有所有必要的导航属性,因此应该可以进行此查询。