2012-04-06 115 views
2

首先,我做了一些搜索這個問題的答案...但我找不到任何東西,因爲我不知道我用什麼功能被稱爲。LINQ:爲什麼我不能在返回的對象中聲明新對象?

以下代碼中的DBEntities由devart爲Oracle數據庫連接生成。

爲什麼第一個例子工作,第二個例子只給我一個System.NullReferenceException?

有效代碼:

using (DBEntities context = new DBEntities()) 
{ 
    var infos = (from info in context.Infos 
       where info.Index == index 
       orderby info.Name 
       select new 
       { 
        Name = info.Name, 
        MRN = info.MRN, 
        UnitNumber = (info.UnitNum == null) ? -1 : (decimal)info.UnitNum, 
        UnitName = (info.UnitName == null) ? String.Empty : info.UnitName 
       }).Distinct(); 

    foreach (var info in infos) 
    { 
     // *do stuff* 
    } 
} 

代碼,讓異常(一旦達到的foreach例外僅見於):

using (DBEntities context = new DBEntities()) 
{ 
    var infos = (from info in context.Infos 
       where info.Index == index 
       orderby info.Name 
       select new Member() 
       { 
        Name = info.Name, 
        MRN = info.MRN, 
        CurrentUnit = new Unit() 
        { 
         UnitNumber = (info.UnitNum == null) ? -1 : (decimal)info.UnitNum, 
         UnitName = (info.UnitName == null) ? String.Empty : info.UnitName 
        } 
       }).Distinct(); 

    foreach (Member info in infos) 
    { 
     // *do stuff* 
    } 
} 

編輯: 我想補充一點,也可以使用:

using (DBEntities context = new DBEntities()) 
{ 
    var infos = (from info in context.Infos 
       where info.Index == index 
       orderby info.Name 
       select new Member() 
       { 
        Name = info.Name, 
        MRN = info.MRN 
       }).Distinct(); 

    foreach (Member info in infos) //Exception is thrown here. 
    { 
     // *do stuff* 
    } 
} 
+4

你有什麼異常? – Thebigcheeze 2012-04-06 22:20:07

+0

@Thebigcheeze System.NullReferenceException – bsara 2012-04-06 22:23:10

+0

是否確定你的集合包含數據? – Tigran 2012-04-06 22:25:09

回答

2

第一個工作原理是因爲您可以從SQL返回這些匿名類型,並且EF可以爲整個表達式生成一條SQL語句。第二個不是因爲你不能在SQL中創建成員類的實例。如果你強制枚舉發生(使用AsEnumerable()),你可以創建Member value客戶端。

在枚舉時總會拋出異常,因爲LINQ在設計上完全是'懶惰'的。如果你想在創建表達式的時候強制它發生(爲了測試的目的,比如說),然後在其末尾添加.ToList()

+0

所以你說我只是'與使用實體使用LINQ時使用CurrentUnit創建對象的新實例,但如果我正在Enumerable對象上使用它,我可以創建該實例嗎?只是澄清。 – bsara 2012-04-06 22:25:11

+0

不,他說,在你的特定情況下,你必須強迫Linq執行,告訴它你現在需要價值。 – 2012-04-06 22:26:21

+2

始終考慮查詢表達式的哪些部分將在數據庫上進行評估,以及哪些部分將在客戶端上評估。在.ToList(),.ToArray(),.AsEnumerable()之前的任何內容都會在SQL Server上發生,所以如果你的表達式不能被評估,那麼它將會失敗。 EF沒有嘗試弄清楚在哪裏放置邊界,只是盲目地認爲它可以儘可能地在SQL中做。 – 2012-04-06 22:27:24

0

而不是

foreach (Member info in infos) //Exception is thrown here. 
{ 
    // *do stuff* 
} 

使用

foreach (var info in infos) //Valid. 
{ 
    // *do stuff* 
} 

這是因爲infos回報anonymus結果。這不是完全Member集合類。

+0

但是在'foreach(Member ...')的例子中,查詢實例化'Member'實例,而不是匿名實例。 – phoog 2012-04-06 22:35:10

+2

@phoog。您不是迭代完全限定的成員集合類,如List 集合類。爲什麼你必須使用var而不是Member類 – wonde 2012-04-06 22:38:19

+1

這是不正確的,如果你用'select new Member()'作爲select子句進行查詢,它將返回一個'IEnumerable '和'foreach(Member。 ..'會工作得很好,另一個原因是異常(參見Hightechrider的答案) – phoog 2012-04-06 22:40:05

相關問題