2011-10-20 37 views
14

只返回單列我似乎在我的代碼寫這篇頗多:強制從DataReader的

using (var reader = cmd.ExecuteReader()) 
{ 
    if (reader.Read()) 
    { 
     result = new User((int)reader["UserId"], reader["UserName"].ToString()); 
    } 

    if (reader.Read()) 
    { 
     throw new DataException("multiple rows returned from query"); 
    } 
} 

有一些內置的方式做到這一點,我不知道?

+3

也許如果你有過查詢的控制,你可以在裏面做一個'TOP 1' .. 。如果你想檢查你的數據庫的完整性,也許你應該在你查詢的WHERE列中放置'UNIQUE INDEX'而不是這樣做。 –

+1

如何在您的sql-query中添加TOP 1? – Stecya

+4

我不想要TOP 1,我想要一個例外。他們根本不是一回事。 – fearofawhackplanet

回答

15

我不知道,但可以此代碼授權到一個擴展方法:

public static R Single<R>(this DataReader reader, Func<DataReader,R> selector) { 
    R result = default(R); 
    if (reader.Read()) 
     result = selector(reader); 
    if (reader.Read()) 
     throw new DataException("multiple rows returned from query"); 
    return result; 
} 

以這樣使用:

using (var reader = cmd.ExecuteReader()) 
{ 
    User u = reader.Single(r => new User((int)r["UserId"], r["UserName"].ToString())) 
} 

從代碼重複拯救你。

+0

我們可以通過爲'SqlCommand'創建一個擴展方法來避免更多重複的代碼。 '用戶u = cmd.Single(...);' –

+0

當然,在這個低級別的API上,有幾個擴展方法可以使它成爲相當有用的東西:) – flq

+0

我不喜歡這個擴展'SqlCommand'這麼多,因爲它沒有實現任何有用的接口。 – fearofawhackplanet

1

如果您正在使用sql來獲取您的數據,這可能有助於您在每個需要使用數據讀取器的實例中刪除那種編碼。

SELECT TOP ([Number of rows you want to be selected]) 
FROM [Table Name] 
WHERE [Condition] 

EX:

SELECT TOP (1) 
FROM tblUsers 
WHERE Username = 'Allan Chua' 

另一個提示使用存儲的過程,使用它們可以儘量減少SQL查詢和不必要的編碼的重複。

8

根據你的目標是什麼,這可能會也可能不會有幫助。如果您需要檢測多行被返回以便引發適當的異常,那麼這將無濟於事。

如果您只想確保只返回一個結果,則可以通過使用此方法獲得性能緩衝。據我所知,數據提供者可以使用它來預期單行結果來優化查詢。

在任何情況下,您要做的就是使用SqlCommand.ExecuteReader創建數據讀取器,但傳入CommandBehavior枚舉(特別是CommandBehavior.SingleRow)中的參數。 ExecuteReader被重載以接受這個。

CommandBehavior enum

SqlCommand.ExecuteReader overload

所以,你的代碼可能是這樣的:

using (var reader = cmd.ExecuteReader(CommandBehavior.SingleRow)) 
{ 
    if (reader.Read()) 
    { 
     result = new User((int)reader["UserId"], reader["UserName"].ToString()); 
    } 
}