加载了Eager的相关对象为null,这些对象是延迟加载的

时间:2012-07-26 15:54:02

标签: asp.net-mvc-3 entity-framework poco eager-loading

我渴望加载(通过使用.Include())相关实体,以便最大限度地减少为特定“大规模”数据网格生成的SQL查询的数量。在POCO中,相关实体是公共虚拟导航属性,这意味着它们是懒惰加载的。我想保留延迟加载这些相关实体的默认行为,因为它最适合我项目的其他部分。

现在,发生的事情是,在急切加载相关实体之后,我可以看到仍然生成了大量的查询。这是仅针对相关实体为空的查询(null因为sql加入“找到”没有相关数据)。

这使我相信EF会在稍后在表示层中访问它们时尝试延迟加载这些实体(认为它们尚未加载)。

我是否错过了一些基本的东西,或者有什么方法可以解决这个问题吗?

示例代码
使用存储库模式,这里有一些简化的方法(省略分页,排序,过滤等)。

通用存储库中的Get方法

public IEnumerable<T> Get(
    Expression<Func<T, object>>[] includes = null)
{
    IQueryable<T> query = set;

    ...

    // Include properies for eager loading
    if (includes != null)
    {
       query = includes.Aggregate(query, 
          (current, include) => current.Include(include));
    }

    ...

    return query.ToList();
}

上面是从服务类调用的,类似这样的

...
context.Licenses.Get(
    includes: new Expression<Func<License, object>>[] { l => l.Comment }
);
...

许可证POCO

public class License
{
    public License()
    {
    }

    // Primitive properties
    public string ID { get; set; }
    public string Name { get; set; }
    ...
    // Navigation properties
    public virtual LicenseComment Comment { get; set; }
    ...
}

LicenseComment POCO

public class LicenseComment
{
    public LicenseComment()
    {
    }

    // Primitive properties
    public string LicenseID { get; set; }
    public string Comment { get; set; }
}

在MVC Razor视图中(或在模型中访问该属性)

<span>@license.Comment</span>


每当我尝试访问null(通过SQL Server Profiler查找)时,就会生成额外的SQL查询,这在我看来Entity Framework延迟加载,即使我急切地包含了这个属性。

3 个答案:

答案 0 :(得分:2)

我无法尝试知道,但我希望不会发生这种情况。无论如何,如果你有一个页面,你不希望延迟加载发生,你只需关闭该页面:

context.Configuration.LazyLoadingEnabled = false;

或者您可以为这些查询关闭代理创建 - 未经过代理的实体无法使用延迟加载:

context.Configuration.ProxyCreationEnabled = false;

答案 1 :(得分:0)

我同意@Ladislav认为它不应该发生并测试“正常”行为如下:

如果您加载许可证,包括评论......

var license = context.Licenses.Include(l => l.Comment).Single(l => l.ID == 1);

... EF将导航属性标记为已加载:

var isCommentLoaded = context.Entry(license).Reference(l => l.Comment).IsLoaded;

无论评论是null还是isCommentLoaded都是true,并且在您访问Comment媒体资源时不会发出延迟加载查询。

即使您不使用预先加载......

var license = context.Licenses.Single(l => l.ID == 1);

... isCommentLoaded将为true ,如果数据库中的注释许可证中的外键为NULL(但它将为{{1}如果外键不是false)。原因是EF总是将NULL语句中的外键加载到上下文中,如果此键为SELECT,EF知道数据库中没有相关注释,并将导航属性标记为已加载避免不必要的延迟加载。

答案 2 :(得分:0)

虽然不完全是你的情况,但我有类似的东西,并且我指出有一个额外的属性访问权限不属于原始包含。