2011-03-28 59 views
1

有人能解釋爲什麼這個異常在下面的LINQ查詢存在的了:例外:空值不能分配與類型System.Int32一個成員是一個非空的值類型

 return (from c in dc.Classifications 
       where c.Id == classificationId 
       select new Classification() 
       { 
        Description = c.Description, 
        ParentId = Convert.ToInt16(c.ParentId), 
       }).Single<Classification>(); 

DC是datacontext,Classification是一個包含int屬性ParentId的類。 ParentId列是來自Sql Server數據庫的可空int。在ParentId字段在數據庫中爲空的情況下,該語句返回InvalidOperationException。

換句話說,爲什麼上面的查詢失敗並且 'int y = Convert.ToInt16(null);'
工作?

+0

當數據庫中的字段爲空時,您希望在ParentID中使用什麼值? – Kipotlov 2011-03-28 15:12:05

+0

int x = Convert.ToInt16(matches.Single()。ParentId);當這個ParentId在db中爲空時,這不會拋出任何異常嗎?......奇怪! – 2011-03-28 15:21:04

+0

如果數據庫字段爲空,我希望ParentId爲零。 – Will 2011-03-28 19:15:33

回答

1

如果c.PartentId可以null,然後Convert.ToInt16(null)會拋出異常。

既然你指出Classification.ParentId是一個整數,是不是有一個原因,你使用 Convert.ToInt16使它變短?你不想要ToInt32嗎?對於這個問題,爲什麼要轉換呢?簡單地說:

ParentId = c.ParentId ?? 0 

...,只是吹毛求疵,在技術上你不需要在這個LINQ表達式的結束指定類型:

.Single<Classification>() 

則可以省略,因爲它是由編譯器決定,只是做:

.Single() 

更新:

哦,我明白了,對不起,我錯讀了你原來的問題。這個問題真的是爲什麼:

int y = Convert.ToInt16(null); 

工作,而Linq2Sql表達式中的同樣的事情會引發異常。

我對此沒有很好的回答,除了指出雖然表達式看起來在代碼中是相同的,但實際上它們是由2個不同的Linq實現處理的。 (與接口相同可以有不同的後臺實現)。

在的情況下:

int y = Convert.ToInt16(null); 

您正在爲Convert.ToInt16直接調用。這似乎將null轉換爲default<T>,其中T是所需的類型(因此在此情況下返回0)。

但是,當在Linq2Sql表達式中使用時,表達式及其投影將交給Linq2Entities或Linq2Sql進行處理。在某個地方可能會有一個錯誤。作爲一個基本的Linq2Objects(或任何你想將它命名),它實際上似乎工作確定:

[TestMethod] // test passes 
public void TestLinqToObjects() 
{ 
    var stuff = new List<int?>() { null }; 
    var y = (from x in stuff 
      select Convert.ToInt32(x)) 
      .First(); 
    Assert.AreEqual(0, y); 
} 

上述的「選擇」的作品,但是把同樣的LINQ表達式針對LINQ2SQL或的EntityFramework收集會導致Linq處理器的不同實現來處理表達式,並且它可能會嘗試對錶達式進行不同的操作,或者將其中的一部分轉換爲SQL語句,或者可能只是存在其他實現不會執行的錯誤。

我知道這並不能真正解決您的問題,但它可能有助於解釋它?

+0

Nullable x = null; int y = Convert.ToInt16(x);導致y = 0。爲什麼當它是LINQ表達式的一部分時會導致異常? – Will 2011-03-28 19:25:17

2

假設你想有0作爲ParentId當它在數據庫中NULL:

return (from c in dc.Classifications 
      where c.Id == classificationId 
      select new Classification() 
      { 
       Description = c.Description, 
       ParentId = Convert.ToInt16(c.ParentId ?? 0), 
      }).Single<Classification>(); 

我的回答還假定,即Classifications.ParentId是類型Nullable<int>/int?的,其價值是null如果列數據庫中爲NULL。

我改變的唯一的東西是轉換中的?? 0部分。如果c.ParentIdnullc.ParentId,則使用0。有關更多信息,請參見?? Operator

0

c.ParentId的類型是int?

您對Convert.ToInt16呼叫隨後在兩個方面打破;它失敗(如這裏),如果ParentId大於short.MaxValue或小於short.MinValue,則失敗。

爲什麼在那裏打電話?去掉它。另外,將Single<Classification>()替換爲SingleOrDefault(),以便它在適當時可以返回null。

+0

可爲空 x = null; int y = Convert.ToInt16(x);導致y = 0。爲什麼當它是LINQ表達式的一部分時會導致異常? – Will 2011-03-28 19:26:42

相關問題