2009-10-15 119 views
3

我有這樣的代碼工作:返回列值化爲IEnumerable

public IEnumerable<string> GetEmpNames() 
{ 
    var cmd = SqlCommand("select [EmpName] from [dbo].[Emp]"); 
    using (var rdr = cmd.ExecuteReader()) 
     while (rdr.Read()) 
      yield return (string) rdr["EmpName"]; 
} 

不過,我不知道是否有一個更好的(LINQish)的方式,不必求助於產量回報。 (和的LINQ to SQL是不是一種選擇:))

+2

它清晰簡潔。完全切換到LINQ to SQL或保持原樣。 「收益率回報」沒有任何問題。 – 2009-10-15 14:51:20

+0

@JoelFan,*收益率回報*有什麼問題?這也是我如何做到的。 – 2009-10-15 14:52:01

+0

@Stan,問題在於你將連接打開的時間超過了它應該是的 – 2009-10-15 15:00:35

回答

5
IEnumerable<string> result = DataContext.ExecuteQuery<string>(sqlstring) 

http://msdn.microsoft.com/en-us/library/bb361109.aspx

+0

我懷疑這會在未執行到枚舉的意義上是惰性的,但不是在單一結果中時間感@ Joel的代碼。不過,我找不到任何相關文件。 – 2009-10-15 15:42:46

+0

數據庫執行是Now(不是懶惰)。我相信行的翻譯也是通過DataContext.Translate方法的Now(不是懶惰)。 – 2009-10-15 15:57:05

3

你不應該這樣做!您的閱讀器需要儘快關閉。您不希望在枚舉期間保持打開狀態。最好只創建一個明確的列表,然後返回。

var cmd = SqlCommand("select [EmpName] from [dbo].[Emp]"); 
List<string> results = new List<string>(); 
using (var rdr = cmd.ExecuteReader()) { 
    while (rdr.Read()) 
     results.Add((string) rdr["EmpName"]); 
} 
return results; 

您可以通過鑄造它放在一個DataReader使用LINQ表達式:

using (var rdr = cmd.ExecuteReader()) { 
    results = (from row in rdr.Cast<DbDataRecord>() 
       select (string)row["EmpName"]).ToList(); 
} 

但是請注意,你需要調用ToList(),或者當您嘗試列舉你會得到一個錯誤因爲讀者已經關閉了。

編輯

似乎是在什麼時候它是開放的什麼一個DataReader實際上做的評論有些混亂。 From MSDN

當正在使用的SqlDataReader的, 的關聯的SqlConnection忙 服務SqlDataReader中,並沒有其他 操作可以上 比閉 它以外的的SqlConnection來執行。在調用SqlDataReader的Close 方法之前,情況就是如此。 例如,在調用 關閉之前,您無法檢索 輸出參數。

因此,您應該儘快關閉以釋放連接。

+0

我不會那樣做。如果你想把它放在一個列表中,讓OP的函數private,並讓你的public方法返回GetEmpNames()。ToList()'。 – 2009-10-15 14:56:04

+1

我會說這是來電者的選擇。使用原始代碼,如果他們有很多工作要做,否則他們可以自己調用ToList()。使用你的代碼,即使調用代碼實際上只是做一些聚合操作,所有的數據都將被緩衝。你*降低*靈活性。 – 2009-10-15 14:58:22

+0

@Jon你認爲可以將連接無限期地打開嗎? – 2009-10-15 15:08:39