2010-07-20 106 views
3

使用接口,我們通常有一個var或一個IQueryable,它將返回一組數據對象,然後我們將這些數據對象轉換爲接口並作爲List或IList返回,像這樣:Casting linq-to-sql的結果

var items = 
from t in SomeTable 
where t.condition == true 
select; 
return items.ToList().Cast<SomeInterface>().ToList(); 

注: items.Cast().ToList() 將編譯,但會在運行時拋出一個InvalidCastException。

有沒有更好的方法? (我把ToList/Cast/ToList放入擴展方法中,但這不是更好...)

return items.CastToList<SomeClass, SomeInterface>(); 

謝謝!

+5

咦?你在問什麼? – SLaks 2010-07-20 17:03:31

回答

3

你在做什麼是正確的(你不能直接在IQueryable調用Cast),但它是次優的,因爲當你真的只需要一個時,你正在創建2個列表。使用AsEnumerable代替第一ToList

return items.AsEnumerable().Cast<SomeInterface>().ToList(); 

調用AsEnumerable會導致Cast要在IEnumerable,不IQueryable評估,因此劇組將在實際對象上完成從數據庫中返回,而不是直接D B。

+0

這就是我所希望的,以避免創建這兩個列表。 – 2010-07-20 18:58:16

2

第一次撥打ToList()有什麼意義?爲什麼不只是items.Cast<SomeInterface>().ToList()

或者,你可以這樣做,而不是:

var items = from t in SomeTable 
      where t.condition == true 
      select (SomeInterface) t; 
return items.ToList(); 

如果t沒有實現SomeInterface它仍然會在運行時失敗,但。

這將做同樣的事情,但不會失敗;相反,它會給你null如果該對象未實現該接口:

var items = from t in SomeTable 
      where t.condition == true 
      select t as SomeInterface; 
return items.ToList(); 
+1

這個問題解釋了ToList的第一個調用,它有很好的理由(儘管它應該是AsEnumerable,而不是ToList)。直接調用IQueryable會導致它在數據庫上執行,這不能工作 – 2010-07-20 17:36:42

0

一些解決方案...

相反,它收集轉換後的數據,你可以考慮做一個投影,同時收集它。

return items.Select(x=>x as SomeInterface).ToList(); 

如果您經常這樣做,擴展方法可能仍然有幫助。它不一定是你提到的Tolist/Cast/ToList。 Cast將已經獲得一個IEnumerable,但是你可以創建一個接受IQueryable的重載,像這樣(未經測試)。

public IEnumerable<TResult> Cast<T, TResult>(this IQueryable<T> input) 
{ 
    return input.AsEnumerable().Cast<TResult>(); 
} 

這將消減你的代碼到這一點:

return items.Cast<SomeClass, SomeInterface>.ToList(); 
+0

我們很近!但由於涉及到演員陣容,我需要一個和一個。謝謝! – 2010-07-20 22:25:14

+0

是的,你說得對。編輯代碼以反映這一點。 – 2010-07-22 22:06:28