我有一段时间让实体框架做我想做的事。我正在编写一个feed聚合器,因此我可以将多个rss提要添加到“FeedList”,它将对所有单个播客进行分组并按pubDate进行排序。
类(除FeedListFeed之外的所有类都具有名为Id的标识列):
这些映射似乎有效:
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中获取Feeds的最新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;
答案 0 :(得分:2)
从地图中删除此行...
modelBuilder.Entity<FeedListFeed>()
.HasKey(x => x.FeedId)
.HasKey(x => x.FeedListId);
...因为它有两个问题:
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;
我认为您在模型类中拥有所有必需的导航属性,因此应该可以进行此查询。