0

我正在试验一些查询以找出获得性能提升的最佳方式。Linq中的IQueryable,IEnumerable和Lists

我知道使用IQueryable优于执行Linq到Sql或Linq到实体数据库查询,并且IEnumerable最适合用于Linq到对象,Linq到xml和内存处理。

我有我的WCF服务如下linq查询。当我尝试和修改调用该控制器的方法,我得到了以下设计时编译错误:

不能隐式转换类型“YeagerTechModel.DropDownLists.ProjectDescription []”到“System.Linq.IQueryable”

注意,ProjectDescription对象被定义如下:

using System; 
using System.Collections.Generic; 
using System.Runtime.Serialization; 
using System.ServiceModel; 

namespace YeagerTechModel.DropDownLists 
{ 
    [DataContract] 
    [Serializable] 
    public partial class ProjectDescription 
    { 
     [DataMember] 
     public Int16 ProjectID { get; set; } 
     [DataMember] 
     public String Description { get; set; } 
    } 
} 

这里是DB方法调用:

public IQueryable<ProjectDescription> GetProjectDropDownList() 
     { 
      try 
      { 
       using (YeagerTechEntities DbContext = new YeagerTechEntities()) 
       { 
        DbContext.Configuration.ProxyCreationEnabled = false; 
        DbContext.Database.Connection.Open(); 

        IQueryable<ProjectDescription> project = DbContext.Projects.Where(w => w.Notes != null).Select(s => 
         new ProjectDescription() 
         { 
          ProjectID = s.ProjectID, 
          Description = s.Description 
         } 
        ); 
        return project; 
       } 
      } 
      catch (Exception ex) 
      { 
       throw ex; 
      } 
     } 

这里是在控制器方法的代码:

IQueryable<ProjectDescription> projectDdl = db.GetProjectDropDownList(); 

现在,IQueryable的,等等,原来的方法来获得来自数据库中的数据如下的性能提升阅读了在此之前的实验后:

public List<ProjectDescription> GetProjectDropDownList() 
     { 
      try 
      { 
       using (YeagerTechEntities DbContext = new YeagerTechEntities()) 
       { 
        DbContext.Configuration.ProxyCreationEnabled = false; 
        DbContext.Database.Connection.Open(); 

        var project = DbContext.Projects.Where(w => w.Notes != null).Select(s => 
         new ProjectDescription() 
         { 
          ProjectID = s.ProjectID, 
          Description = s.Description 
         } 
        ); 

        List<ProjectDescription> myProjects = new List<ProjectDescription>(); 

        myProjects = project.ToList(); 

        return myProjects; 
       } 
      } 
      catch (Exception ex) 
      { 
       throw ex; 
      } 
     } 

在控制器中的代码如下:

IEnumerable<ProjectDescription> projectDdl = db.GetProjectDropDownList(); 

首先的问题是: 马ny查询使用var关键字来推断返回的类型。调用数据库检索记录时使用哪一个?在“VAR”语法或“IQuerable”语法“?

我注意到的第二件事是,在控制器端,一个集合,它总是希望这是很容易转换成IEnumerable的一个List对象。

因此,基于这个前提下,我了解,我的最佳解决办法如下: 对于DB方法调用:

public List<ProjectDescription> GetProjectDropDownList() 
     { 
      try 
      { 
       using (YeagerTechEntities DbContext = new YeagerTechEntities()) 
       { 
        DbContext.Configuration.ProxyCreationEnabled = false; 
        DbContext.Database.Connection.Open(); 

        IQueryable<ProjectDescription> project = DbContext.Projects.Where(w => w.Notes != null).Select(s => 
         new ProjectDescription() 
         { 
          ProjectID = s.ProjectID, 
          Description = s.Description 
         } 
        ); 

        List<ProjectDescription> myProjects = new List<ProjectDescription>(); 

        myProjects = project.ToList(); 

        return myProjects; 
       } 
      } 
      catch (Exception ex) 
      { 
       throw ex; 
      } 
     } 

对于控制器的代码片段,它应该是如下,一切工作正常:

IEnumerable<ProjectDescription> projectDdl = db.GetProjectDropDownList(); 

因此,如果IQueryable提供更好的性能(特别是在过滤和支持延迟加载时),为什么不使用最后的DB方法而不是“var”关键字?

有人可以帮助解释什么应该是最佳方案?

回答

0

无论您使用var还是花时间输出变量的类型都不是问题。你的第二个和第三个例子都编译成正好是相同的代码。

然而,你的第一个实施是比其他两个更好。您的第一个方法返回查询。另外两个返回查询结果

因此,第一个实现允许调用者应用该查询的进一步过滤器/映射/操作,并将它们反映到所调用的数据库查询中,而不是内存中的结果。这也意味着,您在推迟实际执行该查询时,直到您需要时才执行该查询,而不是现在。

该实现确实存在缺陷;你推迟执行,而且在执行查询之前处理底层的上下文。您需要将您的上下文范围限定在“更高”级别,以确保在查询执行之后它尚未处理完毕。

至于错误,您没有显示足够的信息来查看问题所在,但您应该努力修复它,而不是在应用程序中而不是在数据库中执行所有数据操作。

注意:捕捉异常只是为了重新抛出它没有意义。你没有做任何生产,但清除堆栈跟踪。如果你没有任何关系,就不要首先排除异常。

+0

感谢您的回答。但是,调用DB方法的第一个实现的Controller方法不接受返回IQueryable结果。它总是期望ProjectDescription对象的类型为List。 – sagesky36

+0

这就是为什么我推迟,并说我最好的选择将是最后一个基于我以前的评论。 – sagesky36

+0

如果我知道如何使控制器中的代码接受来自ProjectDescription对象的IQueryable结果,那么我会同意第一次实现将是最好的...... – sagesky36