Entity framework 4 EF4-即时加载比延迟加载慢?

Entity framework 4 EF4-即时加载比延迟加载慢?,entity-framework-4,lazy-loading,Entity Framework 4,Lazy Loading,我有一个由几个实体组成的数据模型,所有实体都相互关联,总共有大约80个表 我开始让代码处于生产状态,在这个过程中,我从懒惰地加载所有东西(这使我的开发生活更容易)转变为急切地加载,以防我不需要所有相关数据,或者它只是表示太多数据要发送给客户机,这只是浪费带宽 然而,我只是注意到,至少对于某些实体,急切地加载我所需要的数据要比懒惰地加载所有数据慢得多 下面是一个示例,我可以延迟加载“请求”对象: db.ContextOptions.LazyLoadingEnabled = true; reques

我有一个由几个实体组成的数据模型,所有实体都相互关联,总共有大约80个表

我开始让代码处于生产状态,在这个过程中,我从懒惰地加载所有东西(这使我的开发生活更容易)转变为急切地加载,以防我不需要所有相关数据,或者它只是表示太多数据要发送给客户机,这只是浪费带宽

然而,我只是注意到,至少对于某些实体,急切地加载我所需要的数据要比懒惰地加载所有数据慢得多

下面是一个示例,我可以延迟加载“请求”对象:

db.ContextOptions.LazyLoadingEnabled = true;
request = db.requests.Where(rq => rq.idrequest == rID).FirstOrDefault();
或者急切地:

db.ContextOptions.LazyLoadingEnabled = false;
request = db.request_objects.Include("service_objects.task_objects.task_parameters.parameter_values.address1").Include("service_objects.task_objects.task_parameters.parameter_values.attachment").
                            Include("service_objects.task_objects.task_parameters.parameter_values.phone_nbrs").Include("service_objects.task_objects.task_parameters.parameter_values.stored_texts").
                            Include("service_objects.task_objects.parent_tasks").Include("service_objects.task_objects.contact_objects").
                            Include("service_objects.service_parameters.parameter_values.address1").Include("service_objects.service_parameters.parameter_values.attachment").
                            Include("service_objects.service_parameters.parameter_values.phone_nbrs").Include("service_objects.service_parameters.parameter_values.stored_texts").
                            Include("service_objects.stored_texts").
                            Include("request_attachments.attachment").Include("request_notes.note").
                            Include("request_contacts.contact_objects").Include("contact_objects").
                            Include("contact_objects1").Include("contact_objects2").
                            Include("request_objects_links.request_objects1").Include("stored_texts").
                            Include("company_objects").
                            Where(ro => ro.idrequest_objects == rID).FirstOrDefault();
在大多数情况下,急切加载请求比惰性加载慢数百倍或数千倍(!!!),尽管惰性加载通常会加载大量额外数据。 我的意思是,使用即时加载需要2到3秒,而在大多数情况下(通常不到10毫秒)使用延迟加载需要不到40毫秒(我使用System.diagnostics.Stopwatch获得这些时间)

我不是SQL专家,对SQL优化一无所知,但我不明白为什么加载更少的数据会更昂贵

我有什么见解或明显的错误吗? 谢谢

编辑

从Brokenglass的回答来看,我不够清楚:o)。此代码只是WCF服务功能的一部分,非常简单:

[OperationContract]
public request LoadRequestByID(int rID)
{
  request res = null;
  try
  {
    DBEntities db = new DBEntities();
    res = db.request_objects.Where(ro => ro.idrequest_objects == rID).FirstOrDefault();
  }
  catch (Exception e)
  {
    //Error log
  }
  return res;
}

当我注意到在客户端显示请求的详细信息(调用上述函数后)所花的时间要长得多,而不是延迟加载时,我决定对其进行计时。

您当前正在比较苹果和桔子:

db.ContextOptions.LazyLoadingEnabled = true;
request = db.requests.Where(rq => rq.idrequest == rID).FirstOrDefault();
这只是启用了延迟加载,但加载本身还没有完成——在显式访问这些属性之前,所有相关实体都没有加载


您演示的第二种情况将导致在相应的DB表上进行联接,这自然比仅从一个表中获取一行要慢得多,但它将检索您需要的所有数据。

您目前正在比较苹果和橙子:

db.ContextOptions.LazyLoadingEnabled = true;
request = db.requests.Where(rq => rq.idrequest == rID).FirstOrDefault();
这只是启用了延迟加载,但加载本身还没有完成——在显式访问这些属性之前,所有相关实体都没有加载


您演示的第二种情况将导致在相应的DB表上进行连接,这自然比只从一个表中获取一行要慢得多,但它将检索您需要的所有数据。

这很有趣。实际上,急切加载加载的数据更少并不是真的。它的负载要大得多,因为您的所有包含都被连接到了一起。延迟加载的问题是,每个延迟加载的属性都会导致额外的数据库查询=到数据库的往返。这在本地机器上可能会非常快,但一旦数据库服务器位于网络的其他位置,速度就会非常慢

因此,主要建议如下:

  • 衡量实际生产环境中的性能
  • 确保您的整个图形确实是用延迟加载加载的。您可以忘记在某个地方将单个导航属性标记为虚拟,而您的一半数据将根本不会加载。(如果您有来自T4模板的自动生成实体,则不应发生这种情况)
  • 确保在客户机上传输真正需要的数据。传输所有数据只是为了让一切变得更简单并不总是双赢的解决方案
      这很有趣。实际上,急切加载加载的数据更少并不是真的。它的负载要大得多,因为您的所有包含都被连接到了一起。延迟加载的问题是,每个延迟加载的属性都会导致额外的数据库查询=到数据库的往返。这在本地机器上可能会非常快,但一旦数据库服务器位于网络的其他位置,速度就会非常慢

      因此,主要建议如下:

      • 衡量实际生产环境中的性能
      • 确保您的整个图形确实是用延迟加载加载的。您可以忘记在某个地方将单个导航属性标记为虚拟,而您的一半数据将根本不会加载。(如果您有来自T4模板的自动生成实体,则不应发生这种情况)
      • 确保在客户机上传输真正需要的数据。传输所有数据只是为了让一切变得更简单并不总是双赢的解决方案
      感谢您的回复。这实际上只是将请求实体返回到客户端应用程序的服务函数的一部分。函数本身非常简单:
      [OperationContract]公共请求_对象LoadRequestByID(int rID){request res=null;尝试{DBEntities db=new DBEntities();res=db.request_objects.Where(ro=>ro.idrequest_objects==rID.FirstOrDefault();}catch(异常e){//Error log}返回res;}
      …我假设它在将数据发送到客户端之前加载所有内容,因为延迟加载只发生在数据处于上下文中的情况下。至少我是这样理解的,但可能我错了?无论是哪种方式,在客户端,当急切加载为与延迟加载相反(尽管我只渴望加载我使用的数据)。谢谢!感谢您的响应。这实际上只是将请求实体返回到客户端应用程序的服务函数的一部分。该函数本身非常简单:
      [OperationContract]public request\u objects LoadRequestByID(int-rID){request res=null;尝试{DBEntities db=new DBEntities();res=db.request_objects.Where(ro=>ro.idrequest_objects==rID).FirstOrDefault();}catch(异常e)