2010-10-22 26 views
2

Problème intéressant que j'ai rencontré et qui est totalement logique. J'ai une méthode générique comme ceci:Renvoi de IEnumerable avec utilisation de

public TResult Run<TResult>(Func<SqlDataReader, TResult> resultDelegate) 
{ 
    TResult result; 

    using (SqlDataReader reader = command.ExecuteReader()) // command is SqlCommand with attached SqlConnection 
    { 
     result = resultsDelegate(reader); 
    } 

    // Some other unrelated code (but that's why result has a variable) 

    return result; 
} 

Dans un cas, le type de retour de resultDelegate (TResult) est IEnumerable<object>. Le problème est que la fonction Run renvoie immédiatement en raison de l'exécution différée, en éliminant le SqlDataReader. Plus tard dans le code, lorsque j'essaie de lire les résultats (ce que fait le délégué reader.Read(), je reçois un InvalidOperationException: Invalid attempt to call Read when reader is closed.

Je n'arrive pas à trouver la meilleure façon de faire. , mais je voudrais éviter cela si possible.Je peux aussi déplacer l'instruction using dans le délégué, mais encore une fois, si je peux éviter de le faire pour chaque délégué ce serait bien.Toutes idées?

Répondre

5

Peut-être:

public TResult Run<TResult>(Func<SqlDataReader, TResult> resultDelegate) 
{ 
    TResult result; 

    using (SqlDataReader reader = command.ExecuteReader()) // command is SqlCommand with attached SqlConnection 
    { 
     result = resultsDelegate(reader); 
     if (typeof(TResult) == typeof(IEnumerable<object>)) 
     { 
     var enumerable = result as IEnumerable<object>; 
     if (enumerable != null) 
     { 
      result = enumerable.ToList(); 
     } 
     } 
    } 

    // Some other unrelated code (but that's why result has a variable) 

    return result; 

} 
+0

Idée intéressante - vous êtes obligé d'être une liste concrète, mais en dehors de la portée du délégué. s Conséquences cachées et involontaires (la liste doit être allouée en mémoire). Si je devais suivre cette route, je lancerais probablement une exception si le délégué renvoie IEnumerable; De cette façon, il est évident que ce qui se passe réellement. –

+0

kudos JeffN825 pour une réponse très créative. – pstrjds

+0

Si vous ne gardez pas votre lecteur ouvert, il n'y a aucun moyen d'utiliser l'exécution différée du tout. Vous DEVEZ allouer et énumérer les résultats dans la portée du lecteur. – Jeff