为什么 EF 急切地首先使用 EF 数据库加载所有导航属性

本文关键字:EF 加载 数据库 导航 属性 为什么 | 更新日期: 2023-09-27 18:34:56

我首先使用 EF 数据库,因为我喜欢在 SQL Management Studio 中设计我的数据库,坦率地说,让 Visual Studio 直接从数据库创建所有实体非常容易,而无需执行任何代码。

我在 SQL 事件探查器上注意到,每当我对结果集合调用 ToList(( 时,EF 都会急切地加载对象的所有相关实体。

假设我有一个这样的实体:

public class SomeEntity
{
  public string Name { get; set; }
  public IEnumerable<SomeOtherEntity> ListOfOtherEntites { get; set; }
}

然后,我可以进行查询,获取这些实体的列表:

public IEnumerable<SomeEntity> GetAllOfTheSomeEntities(Guid customerId){
   return dbContex.SomeEntity.Where(x => x.CustomerId == customerId);
}

代码的稍后阶段,我想用这个列表做一些事情(例如在 MVC 的控制器中(,我会在查询上调用 ToList((:

var list = repository.GetAllOfTheSomeEntities(customerId).ToList();

即使我从未在实体上使用属性"ListOfOtherEntites",它仍然被加载到我的服务器内存中。

我知道我不必先在代码中担心这一点,因为我可以使用"虚拟/非虚拟"属性和包含来控制加载 - 但是我该如何先在数据库中执行此操作?

我可以在从数据库加载实体后更改它们;但是如果我稍后更新我的模型,它们就会被重新创建。

为什么 EF 急切地首先使用 EF 数据库加载所有导航属性

您需要

将导航属性标记为virtual,以便在实体框架中启用延迟加载。

public class SomeEntity
{
  public string Name { get; set; }
  public virtual IEnumerable<SomeOtherEntity> ListOfOtherEntites { get; set; }
}

简单地修改生成的代码不能解决问题吗?

如果您遇到延迟加载问题,那么我可能会建议您在 EF 上下文中关闭延迟加载。

public class YourContext : DbContext
{
    public YourContext()
    {
        this.Configuration.LazyLoadingEnabled = false;
    }
}

然后,您可以使用 LINQ 的 .Include() 方法包含相关实体,如下所示:

var posts = context.Blogs.Include(b => b.Posts).ToList();