2011-10-20 24 views
14

wydaje mi się napisać ten sporo w moim kodu:Wymuszanie tylko jeden wiersz zwrócony z 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"); 
    } 
} 

Czy istnieje jakiś zbudowany w sposób do tego, że nie wiem o zrobić?

+3

Może jeśli masz kontrolę nad kwerendy, można zrobić 'top 1 'w nim .. Jeśli chcesz sprawdzić integralność bazy danych, może powinieneś umieścić 'UNIKALNY INDEKS 'w kolumnach zapytania" WHERE ", zamiast tego zrobić. –

+1

Co powiesz o dodaniu TOP 1 do zapytania sql? – Stecya

+4

Nie chcę TOP 1, chcę wyjątek. To nie jest to samo. – fearofawhackplanet

Odpowiedz

15

nie wiem, ale ten kod może być delegowane na metodę rozszerzenia:

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; 
} 

być używane tak:

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

oszczędzając od powielania kodu.

+0

Możemy uniknąć nawet bardziej powielonego kodu, tworząc metodę rozszerzenia dla 'SqlCommand'. 'Użytkownik u = cmd.Single (...);' –

+0

Oczywiście, na tym niskim poziomie interfejsu API, z kilkoma metodami rozszerzenia, możesz go ukształtować tak, aby był całkiem użyteczny :) – flq

+0

Nie podoba mi się rozszerzenie na 'SqlCommand' tak bardzo, ponieważ nie implementuje żadnego użytecznego interfejsu. – fearofawhackplanet

1

Jeśli używasz sql do pobierania twoich danych, może to pomóc, pozwalając na usunięcie tego rodzaju kodowania w każdym przypadku, w którym musisz użyć czytnika danych.

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

EX:

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

Innym zastosowaniem końcówki, wykorzystując je mogą zminimalizować powtórzenia i niepotrzebnych zapytań SQL kodowania.

8

Może to, ale nie musi pomóc, w zależności od celu. Jeśli chcesz wykryć, że zwrócono wiele wierszy w celu wygenerowania odpowiedniego wyjątku, to nie pomoże.

Jeśli chcesz tylko upewnić się, że zwracany jest tylko jeden wynik, możesz potencjalnie uzyskać efekt wydajności za pomocą tej metody. Z tego co rozumiem, dostawcy danych mogą wykorzystać to do zoptymalizowania zapytania w oczekiwaniu na wynik w jednym wierszu.

W każdym razie, należy użyć SqlCommand.ExecuteReader, aby utworzyć swój czytnik danych, ale przekazać argument z wyliczenia CommandBehavior (w szczególności CommandBehavior.SingleRow). ExecuteReader jest przeciążony, aby to zaakceptować.

CommandBehavior enum

SqlCommand.ExecuteReader overload

Więc twój kod może wyglądać następująco:

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