如何编写where查询以仅包含1个child实体

时间:2012-06-04 17:24:01

标签: c# linq entity-framework entity-framework-4

我有实体

Blog{ blogId, name, creatorUserId }

BlogSettings{ blogId, userId, column1  }

现在我有一个接受blogIduserId的方法,我正在查询Blog(不是BlogSettings

Blog包含BlogSettings

的集合

我该怎么做?

如果我写context.Blogs.Include("BlogSettings").Where( b => b.BlogId == blogId)效率非常低,因为我只需要其userId == userId的BlogSettings。

Note:我不是在查询BlogSettings。正如您所看到的,我正在查询Blog集合。

4 个答案:

答案 0 :(得分:1)

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);
    //
}

答案 1 :(得分:0)

虽然您在Blog上正在查询,但您可能会发现针对BlogSettings撰写查询并添加.Include("Blog")更有效。

Presumaby你只有一个BlogSettings用于UserId和BlogId的组合;也许这是由一个独特的约束强制执行的。如果是这种情况,这将非常快:

    var blogAndSettings = (from s in context.BlogSettings
                                            .Include("Blog")
                           where s.BlogId = blogId && s.UserId = userId
                           select s).SingleOrDefault();

这需要您创建一个名为BlogSettings的{​​{1}}到Blog的导航属性。

答案 2 :(得分:0)

这将执行BlogBlogSettings表之间的联接,但只是实现BlogSetting个实体。

var settings = context.Blogs.Where( b => b.BlogId == blogId && b.CreatorUserId = userId)
                            .SelectMany(x => x. BlogSettings);

答案 3 :(得分:-1)

context.Blogs.Include("BlogSettings").SingleOrDefault( b => b.BlogId == blogId);