2011-03-14 23 views
6

我正在使用EF。這是我的LINQ查詢LINQ to EF有什麼問題?

public List<Tuple<int, string>> GetList() 
{ 
    return (from c in DALContext.MST 
      select new Tuple<int, string>(c.CD, c.NAME)).ToList(); 
} 

當我打電話的GetList()拋出異常:只有無參構造函數和初始化在LINQ支持到實體

相反,當我重寫此查詢:

List<Tuple<int, string>> lst = new List<Tuple<int, string>>(); 
var query= (from c in DALContext.MST 
      select new{c.CD, c.NAME}); 
foreach (var item in query) 
{ 
    lst.Add(new Tuple<int,string>(item.CD,item.NAME)); 
} 
return lst; 

它只是正常工作。我的第一個查詢有什麼問題?

回答

11

其他的答案是什麼回事正確的,但我沒有看到任何人提起,使你的代碼工作的最佳方法:AsEnumerable()

public List<Tuple<int, string>> GetList() 
    { 
     return (from c in DALContext.MST.AsEnumerable() 
       select Tuple.Create(c.CD, c.NAME)).ToList(); 
    } 

AsEnumerable方法作爲代碼,應該是之間的邊界轉換爲SQL並在數據庫服務器中執行,以及在從數據庫獲得響應後應在內存中執行的代碼。把它放在表名之後告訴EF從MST表中獲取所有記錄,然後運行下面的代碼,該代碼根據返回的值創建元組。

我將new Tuple<int, string>更改爲Tuple.Create,主要是因爲我不喜歡輸入泛型類型參數。

+1

「AsEnumerable()」與使用「ToList()」還是「ToArray()」有什麼不同? – Despertar 2012-12-16 01:35:16

+1

@Despertar - ToList()和ToArray()必須遍歷查詢結果以構建列表或數組。在上面的例子中,如果用'ToList()'替換'AsEnumerable()',那麼你會遍歷結果兩次。使用'AsEnumerable()'你只需循環一次,因爲'AsEnumerable()'不會消耗序列。 – 2012-12-16 19:27:11

6

LINQ to EF處理查詢有點不同於LINQ to SQL。在LINQ to EF,你不能把一個帶參數的構造函數在LINQ的表情,就像你在代碼的第一位在這裏做的:

from c in DALContext.MST 
select new Tuple<int, string>(c.CD, c.NAME) 

元組的構造函數接受兩個參數,這是不允許的在LINQ到EF。

原因解釋here

這部分是想 LINQ到實體更明確 約之間您的查詢字詞部分 執行服務器 ,哪些在邊界的問題部分在客戶端執行。

使用LINQ到SQL,例如,它是 可以寫一個LINQ查詢其 不僅涉及數據從服務器 和功能的服務器上,但也 功能,只能在 客戶端和執行將它們混合在一起,即 。然後,LINQ to SQL提供程序 將盡最大努力解決 問題,並執行它可以在服務器上運行的部分以及在客戶端上運行 的其他部分。這很好,因爲它 很容易只寫任何你想要的查詢 ,並且如果可能的話會起作用。在另一方面,它 不是那麼好,如果你不小心寫 查詢哪裏可以 在服務器上執行的唯一部分是返回的所有數據 中的一個或多個表中的最 最基本的東西,然後有 所有過濾發生在客戶端 (帶有非常討厭的後果)。

使用LINQ to Entities,邊界 更明確。當你寫一個 LINQ查詢針對LINQ to實體 IQueryable的執行,整個 查詢在服務器上執行,而如果 查詢的某些部分不能 在服務器上執行,那麼 明確的邊界必須創建 類似ToQueryable()或 ToList()。一旦執行該查詢 並檢索到數據,則可以使用LINQ to Objects 進一步優化 查詢是否如此選擇。這種方式 你明確知道你的 界限是哪裏,並且它更容易 跟蹤性能問題和 一樣。 的一個相關限制是,實體的LINQ 中的select語句可以創建匿名類型 或其他類型,只要它們具有默認構造函數 參數。這最大限度地減少了選擇語句具有主要 副作用的機會 。

1

你的類需要有LINQ到EF參數的構造函數,你必須初始化它是這樣的:

public List<Tuple<int, string>> GetList() 
{ 
    return (from c in DALContext.MST 
      select new Tuple<int, string>(){CD = c.CD, Name = c.NAME}).ToList(); 
} 

編輯:

如果您未在位置添加無參數構造函數TUPLE(這裏Tuple不是一個類本身),那麼你沒有選擇使用Linq到EF,但要做爲一個兩步過程:

public List<Tuple<int, string>> GetList() 
{ 
    List<MST> mstList = (from c in DALContext.MST 
         select c).ToList(); 

    List<Tuple<int, string>> tupleList = new List<Tuple<int, string>>(); 

    mstList.foreach(c => tupleList.add(new Tuple(c.CD, c.Name))); 

    return tupleList; 
} 
+0

不幸的是,這不起作用,因爲大括號只是用於設置屬性的語法糖,而元組沒有可分配的CD或Name屬性(或者任何可分配的屬性)。 – 2011-03-14 06:09:33

2

或者你可以只寫

var query= (from c in DALContext.MST 
      select new{c.CD, c.NAME}).ToList().Select(x=>new Tuple(x.CD, x.NAME)); 

這樣做的好處是隻從DB帶給你所需要的兩列。

+0

關於只選擇你需要的兩列,這是一個很好的觀點,但我仍然選擇'AsEnumerable',然後'ToList'兩次調用'ToList'。 – 2012-07-24 00:41:15