2012-03-28 26 views
3

我有我的LINQ從數據庫中獲取到SQL控制器類的層次結構,並顯示該大類爲needed.Let我解釋一下:IEnumerable的<T>莫名其妙地被轉化爲EntitySet的<T>

BigProduct 
IEnumerable<Review> 
//...some generic types 


Review 
IEnumerable<Comment> 
//...some generic types 


Comment 
//...some generic types 

所以在我的控制器我獲取大產品並將其傳遞給主視圖,然後將foreviews中的評論傳遞給部分視圖,並在這些部分視圖中的每個視圖中,我有另一個應該將所有註釋列爲部分視圖的foreach。

這些類型被定義爲Ienumerable類,並且這個DLL可以很好地處理Web表單,現在當我將鼠標懸停在剃刀的foreach循環中時,它說它是EntitySet而不是IEnumerable,並且我得到「null exception:acessed處理後的上下文「,這就是我將它作爲IEnumerable傳遞的原因,因爲我在一個地方獲取所有內容。什麼可能是這種行爲的原因?我沒有改變這個以前用webforms正常工作的dll。

更新:正如我所說的,它在WebForms中運行良好,我打電話給.ToList()以在選擇數據時從IQueryable中獲取IEnumerable!

回答

2

當您返回對接口類型的引用時,如IEnumerable<T>,引用仍然指向其運行時類型實現該接口的對象。更一般地說,無論何時通過它實現的接口或通過繼承鏈中的基類來引用對象,您仍然指的是對象的派生類型最多的實例。

例如:

object o1 = new object(); 
object o2 = "I am a string."; 
object o3 = 42; 

Console.WriteLine(o1.GetType()); 
Console.WriteLine(o2.GetType()); 
Console.WriteLine(o3.GetType()); 

IComparable ic1 = "I am a string."; 
IComparable ic2 = 42; 

Console.WriteLine(ic1.GetType()); 
Console.WriteLine(ic2.GetType()); 

輸出:

System.Object 
System.String 
System.Int32 
System.String 
System.Int32 

如果你想將數據複製到另一個對象也實現IEnumerable<T>,你需要編寫一些代碼來做到這一點。正如其他人所建議的那樣,撥打ToList()是實現此目的的一種簡單方法。

9

僅僅因爲你聲明它作爲IEnumerable<T>,不改變執行時間類型。因此,當您將它傳遞給您的視圖時,視圖將在編譯時知道它是IEnumerable<T>,但是當您在調試時將鼠標懸停在其上時,您會看到實際的類型。 (這不是在什麼時候,你都在Razor視圖上空盤旋Comment清楚,但我強烈嫌疑這是在調試會話中。)

如果你想利用數據,這樣的副本你可以處理上下文,只需撥打ToList()並返回結果 - 這將代替List<T>

請注意,這種編譯時/執行時間差異與LINQ或MVC無關。你可以非常容易地看到同樣的事情,沒有什麼複雜的:

object value = "hello"; 

編譯時valueobject,它會阻止你要求它Substring等。但是,如果您將鼠標懸停在調試會話中的value上(或在「監視」或「本地」窗口中查看它),則會看到執行時間類型仍爲string

編輯:從您的編輯:

我打電話.ToList()從IQueryable的IEnumerable的獲取在選擇數據時!

我真的想看到的代碼,因爲我不你只是使用類似相信:

return query.ToList(); 

如果你返回調用ToList()的結果,不會EntitySet

+0

當這一切,喬恩,你真的把我趕走了!這不像你需要更多的代表,但你一直拋出這些快速,正確,易於理解的答案!這讓我別無選擇,只能爲您的答案投票。啊! – 2012-03-28 17:49:03

+0

@DanielPratt:是否讓你感覺更好,知道早餐後的積分不會影響我的代表? – 2012-03-28 17:51:34

+1

有點。謝謝。 – 2012-03-28 17:56:12

相關問題