如何编写一个 where 查询以仅包含 1 个子实体
本文关键字:包含 实体 查询 where 何编写 一个 | 更新日期: 2023-09-27 18:36:17
我有实体
Blog{ blogId, name, creatorUserId }
BlogSettings{ blogId, userId, column1 }
现在我有一个接受blogId
和userId
的方法,我正在查询Blog
(不是BlogSettings
)
Blog
包含BlogSettings
的集合。
我应该怎么做?
如果我写context.Blogs.Include("BlogSettings").Where( b => b.BlogId == blogId)
那将非常低效,因为我只需要其用户ID == userId的博客设置。
Note:
我不是在博客设置上查询。如您所见,我正在查询博客集合。
var blogWithSetting = context.Blogs
.Where(b => b.BlogId == blogId)
.Select(b => new
{
Blog = b,
BlogSetting = b.BlogSettings.FirstOrDefault(bs => bs.UserId == userId)
})
.SingleOrDefault();
if (blogWithSetting != null)
{
Blog blog = blogWithSetting.Blog;
//
}
此类投影是在单次往返数据库时获取结果的唯一方法,因为使用 Include
进行预先加载不支持对包含的子集合进行任何筛选或排序。如果不禁用更改跟踪并且关系不是多对多,则blog.BlogSettings
将自动填充单个加载的BlogSetting
。否则,必须使用结果对象的属性手动填充集合:
if (blogWithSetting != null)
{
Blog blog = blogWithSetting.Blog;
blog.BlogSettings = new List<BlogSetting>();
blog.BlogSettings.Add(blogWithSetting.BlogSetting);
//
}
虽然名义上您是在Blog
上查询,但您可能会发现针对BlogSettings
编写查询并添加.Include("Blog")
更有效。
Presumaby,对于UserId和BlogId的组合,你只有一个BlogSettings
;也许这是由一个独特的约束强制执行的。 如果是这种情况,这将非常快:
var blogAndSettings = (from s in context.BlogSettings
.Include("Blog")
where s.BlogId = blogId && s.UserId = userId
select s).SingleOrDefault();
这将要求您创建从BlogSettings
到Blog
的名为 Blog
的导航属性。
这将执行Blog
表和BlogSettings
表之间的联接,但只是具体化BlogSetting
实体。
var settings = context.Blogs.Where( b => b.BlogId == blogId && b.CreatorUserId = userId)
.SelectMany(x => x. BlogSettings);
context.Blogs.Include("BlogSettings").SingleOrDefault( b => b.BlogId == blogId);