使用 DTO 在实体框架中延迟加载

Posted

技术标签:

【中文标题】使用 DTO 在实体框架中延迟加载【英文标题】:Deferred loading in Entity Framework using DTO 【发布时间】:2014-04-28 02:11:27 【问题描述】:

我对使用实体框架的延迟加载功能一直面临的这个问题感到非常困惑。 我知道触发数据库查询的扩展,如 .ToList()、.Count() 等。 我的问题是,如果您使用 IEnumerable DTO 作为返回类型,这会触发数据库查询吗?

例如,您有以下 DTO:

public DtoUser

   public string Name  get; set; 
   public int Age  get; set; 

我在你的业务层有这个方法:

public BLLUser

   public IEnumerable<User> GetAllUser
   
      var output = from u in context.User
                   select new DtoUser
                   
                      Name = u.Name,
                      Age = u.Age
                   ;
   

我将其称为:

private void GetUserOnBll()

    using (BLLUser b = new BLLUser())
    
       var dtoUser = b.GetAllUser();

       // can I still do this without triggering the database query
       // or the query is already been triggered
       // since the return type is an IEnumerable DTO
       var filtered = dtoUser.Where(n => n.Name == "TEST");
    

“b.GetUser()”方法会触发数据库查询还是我必须使用 .ToList() 来触发查询?

【问题讨论】:

【参考方案1】:

b.GetUser() 不会触发数据库查询,dtoUser.Where(n =&gt; n.Name == "TEST") 也不会触发查询。不同的执行意味着它只会在你“使用”它时执行数据库查询,例如 foreach 子句或 SingleOrDefault()/Count()/...

所以你上面的程序会做你想做的事。但是会有性能问题。生成的 SQL 会喜欢 Select Name, Age from User 它将所有记录从数据库中获取到内存中,在内存中进行过滤,然后返回过滤后的记录。如果要在数据库端进行过滤,应将 IEnumerable 替换为 IQueryable

【讨论】:

嗨,泰迪,你的解释真的很棒!它有助于清除我脑海中的所有乌云!只是跟进,这是一个经验法则,即使用 IEnumerable 作为返回类型将在过滤之前首先检索所有记录? @arvstracthoughts 并非总是“所有”记录,这取决于您的代码。可以说,ASEnumberable() 之后的所有过滤条件都不会在数据库端应用。例如:context.User.Take(10).AsEnumberable().Take(2); ==> 将从数据库中检索前 10 条记录到内存中,然后返回前 2 条。【参考方案2】:

创建 DtoUser 列表的属性

并通过在构造函数中调用您的函数来分配值。如果您需要示例代码,请告诉我。

另一件事我不知道您如何调用和获取我建议使用 IQueryable 而不是 IEnumerable 的上下文,因为数据库中的 IQueryable 句柄和服务器内存中的 IEnumerable 句柄。

问候 普布都

【讨论】:

以上是关于使用 DTO 在实体框架中延迟加载的主要内容,如果未能解决你的问题,请参考以下文章

在 Spring 中延迟加载 DTO 字段

延迟加载 - (实体框架)底层连接意外关闭

如何使用实体框架将大量数据延迟加载到 GridView [关闭]

C# - 实体框架代码优先,延迟加载不起作用

使用实体框架更新数据库记录(延迟加载和虚拟属性)

实体框架 - 停止按需延迟加载相关实体?