查询连接表时未加载子实体

时间:2011-03-03 17:38:02

标签: c# linq-to-entities

我有一个多对多关系,其中Content包含指向标记的ContentTags。我在我的实体上放置了相关的[Include]属性来创建属性。

如果我写了枚举ObjectContext.Contents.Include("ContentTags.Tag"),那么我会按预期包含ContentTags和Tags。当我使用连接时,我的内容实体中缺少ContentTags:

var contentsForTag =
    from c in ObjectContext.Contents.Include("ContentTags.Tag")
    join ct in ObjectContext.ContentTags on c.Id equals ct.ContentId
    join t in ObjectContext.Tags on ct.TagId equals t.Id
    where t.Name.ToLower().Contains(lowerTag)
    select c;

有什么想法在这里发生了什么?

3 个答案:

答案 0 :(得分:2)

我不确定为什么会这样,但我认为这是因为矛盾。 连接说EF应该只加载包含lowerTag的标签,但Include表示应该加载所有标签。我猜EF不能解决这个问题,这就是为什么没有包含它。您应该能够在没有连接的情况下编写查询

var contentsForTag =
    from c in ObjectContext.Contents.Include("ContentTags.Tag")
    where c.ContentTags.Any(ct => ct.Tag.Name.ToLower().Contains(lowerTag))
    select c;

答案 1 :(得分:1)

尝试以下方法:

var anonType =
    from c in ObjectContext.Contents
    join ct in ObjectContext.ContentTags on c.Id equals ct.ContentId
    join t in ObjectContext.Tags on ct.TagId equals t.Id
    where t.Name.ToLower().Contains(lowerTag)
    select new { Contents = c, ContentTags = ct, Tags = t }).AsEnumerable();

IList<Contents> contentsForTag = anonType.Select(c => c.Contents).ToList();

如果您将所有相关表格放入匿名类型,EF将了解您实际上需要所有这些信息并将其恢复。最好的部分是EF也将负责自动修复,这意味着所有关系都将得到维护。示例的最后一行只是将所需的对象从匿名类型提取到强类型列表中,但是图表的其余部分仍然存活且很好。

答案 2 :(得分:0)

听起来像是“懒惰负载”与“急切负载”差异。 Content类的Tags集合存储在子表中。包括EF在内的许多ORM尝试“延迟加载”集合和其他多对一引用,因为它不知道您是否需要它们,如果不这样做,那将浪费带宽。但是,这意味着您的标记在检索到的实例中不可用。要告诉L2E,是的,您确实需要标记,指定在构建上下文时应该“急切地”遍历子引用。