2011-10-20 14 views
14

mi sembra di scrivere questo un bel po 'nel mio codice:Enforce unico singolo riga restituita dal 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"); 
    } 
} 

c'è qualche costruito in modo per fare questo che io non so?

+3

Forse se si ha il controllo della query, si può fare un 'TOP 1' in esso .. Se vuoi verificare l'integrità del tuo database, forse dovresti mettere un 'UNICO INDICE' contro le colonne della tua query 'WHERE' di te invece di farlo. –

+1

Cosa ne pensi di aggiungere TOP 1 alla tua query sql? – Stecya

+4

Non voglio un TOP 1, voglio un'eccezione. Non sono affatto la stessa cosa. – fearofawhackplanet

risposta

15

Non so, ma questo codice può essere delegata in un metodo di estensione:

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

da utilizzare così:

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

si Salvataggio da duplicazione del codice.

+0

Potremmo evitare codice ancora più duplicato creando un metodo di estensione per 'SqlCommand'. 'User u = cmd.Single (...);' –

+0

Certo, su quell'API di basso livello, con un paio di metodi di estensione puoi modellarlo come roba abbastanza utilizzabile :) – flq

+0

Non mi piace l'estensione su 'SqlCommand' tanto perché non implementa alcuna interfaccia utile. – fearofawhackplanet

1

Se si sta utilizzando un file sql per recuperare i dati, ciò potrebbe essere utile consentendo di rimuovere quel tipo di codifica in ogni istanza che è necessario utilizzare un lettore di dati.

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' 

Un altro uso punta stored procedure, il loro utilizzo potrebbe ridurre al minimo la ripetizione di query SQL e codifica inutili.

8

Questo può o non può aiutare a seconda di quale sia il tuo obiettivo. Se è necessario rilevare che sono state restituite più righe per generare un'eccezione appropriata, non sarà di aiuto.

Se si desidera solo assicurarsi che venga restituito un solo risultato, è possibile ottenere un aumento delle prestazioni utilizzando questo metodo. Da quello che ho capito, i fornitori di dati possono utilizzare questo per ottimizzare la query in previsione di un risultato di una singola riga.

In ogni caso, ciò che si vorrebbe fare è utilizzare SqlCommand.ExecuteReader per creare il proprio lettore di dati, ma passare un argomento dall'enumerazione CommandBehavior (in particolare CommandBehavior.SingleRow). ExecuteReader è sovraccarico per accettarlo.

CommandBehavior enum

SqlCommand.ExecuteReader overload

Quindi il codice potrebbe essere simile a questo:

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