2014-11-21 63 views
0

以下查詢由多個INNER JOIN子句組成。應引用一個空變量異常

Student表中有很多外鍵在查詢中被替換爲名稱。我正在使用下面的LEFT OUTER JOIN查詢。請注意,中的Students可以是null。這意味着marksGroup.DefaultifEmpty()也可能會返回null。因此,如果我在最後一行中只輸入m而不是m != null ? m.MarkName : "-- Not marked --",那麼當m爲空時,代碼IMO應該引發異常,因爲我指的是這個變量,但它沒有。在我構建此查詢的示例上,編譯器拋出異常。請參閱代碼:

var result = from st in dbContext.Students where st.DepartmentID == 17 
      join d in dbContext.Departments on st.DepartmentID equals d.DepartmentID 
      join sv in dbContext.SoftwareVersions on st.SoftwareVersionID equals sv.SoftwareVersionID 
      join stat in dbContext.Statuses on st.StatusID equals stat.StatusID 
      join m in dbContext.Marks on st.MarkID equals m.MarkID into marksGroup 
      from m in marksGroup.DefaultIfEmpty() 
      select new 
      { 
       student = st.StudentName, 
       department = p.DepartmentName, 
       software = sv.SoftwareVersionName, 
       status = st.StatusName, 
       marked = m != null ? m.MarkName : "-- Not marked --" 
      }; 

我錯過了什麼。我仍然是初學者,在C#LINQ

+1

''[...]如果我只把米''。引用該對象不會引發異常。但是,對其執行任何操作,**都會拋出一個**。也就是說,試圖調用一個方法或一個屬性。例如,'marked = m'不應該拋出任何異常,你只是引用該對象。 'marked = m.MarkName',但是,如果'm == null'應該拋出一個** NullReferenceException **。 – 2014-11-21 11:14:14

+0

你的意思是你認爲'marked = m'應該拋出異常嗎? – 2014-11-21 11:14:22

+0

@MatiCicero謝謝Mati。這解釋了我和這個例子之間的區別。我再次查看了示例代碼,作者確實試圖引用空對象的屬性:)乾杯! – Celdor 2014-11-21 11:26:32

回答

1

當您針對SQL後端執行LINQ語句(我假設您在此有實體框架)時,整個語句被翻譯成SQL並由數據庫引擎執行。

所以這是.NET運行時做什麼:

  • 翻譯的聲明(這是一個Expression)轉換成SQL
  • 通過ADO.Net發送SQL數據庫。
  • 接收SQL結果集(基本上是一個行數組,其中一行本身就是一個值數組)。
  • 從這些行創建對象。

在你的情況下,要創建的對象可以安全地通過部分

select new 
{ 
    student = st.StudentName, 
    department = p.DepartmentName, 
    software = sv.SoftwareVersionName, 
    status = st.StatusName, 
    marked = m.MarkName 
} 

.NET運行時關注的是創建一個匿名類型的實例,並設置唯一定義它的屬性來自結果集中的一行。在某些行中,marked的值可能爲null,因此marked將在該特定對象中設置爲null。 .Net運行時不處理那裏的MarksGroup對象。

當然,在LINQ中,對象會完全不同。有空檢查是絕對必要的,以防止空對象引用。