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