2009-10-15 6 views
3

Je possède ce travail de code:valeurs de la colonne de retour comme 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"]; 
} 

Cependant, je me demande s'il y a une meilleure (LINQish) façon, ne pas avoir à recourir à retour de rendement. (Et LINQ to SQL est pas une option :))

+2

C'est clair et concis. Activez complètement LINQ to SQL ou laissez-le tel quel. Il n'y a rien de mal à «rendement rendement». –

+0

@JoelFan, qu'est-ce qui ne va pas avec * yield return *? C'est comme ça que je le ferais aussi. –

+0

@Stan, le problème est que vous laissez votre connexion ouverte plus longtemps que ce qu'elle devrait être –

Répondre

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

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

+0

Je soupçonne que ce sera paresseux dans le sens non-exécuté-jusqu'à-énumération, mais pas dans le seul-résultat-à-un sens du temps du code de @ Joel. Cependant, je n'ai trouvé aucune documentation à ce sujet. –

+0

L'exécution de la base de données est maintenant (pas paresseux). Je crois que la traduction de lignes est également maintenant (pas paresseux) via la méthode DataContext.Translate. –

3

Vous ne devriez pas faire ça! Votre lecteur doit être fermé dès que possible. vous ne voulez pas le garder ouvert pendant la durée de l'énumération. Il est préférable de simplement créer une liste explicite et de la renvoyer.

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; 

Vous pouvez utiliser des expressions Linq sur un DataReader en le jetant:

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

Mais remarquez que vous besoin appeler ToList(), ou vous obtiendrez une erreur lorsque vous essayez d'énumérer parce que le lecteur a déjà été fermé.

Modifier

Il semble y avoir une certaine confusion dans les commentaires au sujet de ce qu'un DataReader ne fait quand il est ouvert. From MSDN:

Alors que le SqlDataReader est utilisé, le SqlConnection associé est occupé au service de la SqlDataReader, et aucune autres opérations peuvent être effectuées sur SqlConnection autre que la fermeture il. C'est le cas jusqu'à ce que la méthode Close de SqlDataReader soit appelée. Par exemple, vous ne pouvez pas récupérer les paramètres de sortie tant que vous n'avez pas appelé Fermer.

Par conséquent, vous devriez le fermer dès que possible pour libérer la connexion.

+0

Je ne ferais pas ça. Si vous voulez le mettre dans une liste, faites la fonction 'private' d'OP et faites en sorte que votre méthode' public' renvoie 'GetEmpNames(). ToList()'. –

+1

Je dirais que c'est le choix de l'appelant. Avec le code original, ils peuvent appeler 'ToList()' eux-mêmes s'ils ont beaucoup de travail à faire autrement. Avec votre code, toutes les données vont être tamponnées même si le code appelant va réellement faire quelque chose comme une agrégation. Vous réduisez * la flexibilité. –

+0

@Jon Vous pensez que c'est juste de laisser la connexion ouverte indéfiniment comme ça? –

Questions connexes