3

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

现在,在预先加载相关实体之后,我可以看到仍然有相当数量的查询生成。这是仅针对为空的相关实体的查询空只是因为 sql 连接“发现”没有相关数据)。

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

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

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

通用存储库中的获取方法

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; }
    ...
}

许可证评论 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 的 License.Comment(通过 SQL Server Profiler 查找)时,都会生成额外的 SQL 查询,在我看来,实体框架延迟加载会启动,即使我急切地包含了这个属性。

4

3 回答 3

2

我无法尝试知道,但我希望这不应该发生。无论如何,如果您有一个不希望发生延迟加载的页面,您可以简单地关闭该页面:

context.Configuration.LazyLoadingEnabled = false;

或者您可以关闭这些查询的代理创建 - 未代理的实体不能使用延迟加载:

context.Configuration.ProxyCreationEnabled = false;
于 2012-07-27T08:02:10.437 回答
1

我同意@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 如果外键不是)。原因是 EF 总是将语句中的外键加载到上下文中,如果这个键是EF 知道数据库中没有相关注释并将导航属性标记为已加载以避免不必要的延迟加载。NULLfalseNULLSELECTNULL

于 2012-07-27T12:32:32.913 回答
0

虽然不完全是您的情况,但我有类似的情况,我指出有一个额外的属性访问不是原始包含的一部分。

于 2013-12-03T18:29:55.140 回答