2009-05-26 4 views
1

J'ai un calque dal avec beaucoup de méthodes, tous appellent des procédures stockées, certaines listes de retour (donc avec une utilisation de SqlDataReader), d'autres seulement une valeur spécifique.Refactor code en utilisant l'instruction

J'ai une méthode d'assistance qui crée le SqlCommand:

protected SqlCommand CreateSprocCommand(string name, bool includeReturn, SqlDbType returnType) 
    { 
     SqlConnection con = new SqlConnection(this.ConnectionString); 
     SqlCommand com = new SqlCommand(name, con); 
     com.CommandType = System.Data.CommandType.StoredProcedure; 

     if (includeReturn) 
      com.Parameters.Add("ReturnValue", returnType).Direction = ParameterDirection.ReturnValue; 

     return com; 
    } 

Maintenant, ma moyenne de regard du corps de la méthode (trop simplifiée) comme:

SqlCommand cmd = CreateSprocCommand("SomeSprocName"); //an override of the above mentioned method 
try { 
    cmd.Connection.Open(); 
    using (var reader = cmd.ExecuteReader()) { 
     //some code looping over the recors 
    } 
    //some more code to return whatever needs to be returned 
} 
finally { 
    cmd.Connection.Dispose(); 
} 

est-il un moyen de factoriser cela, de sorte que Je ne vais pas perdre ma fonction d'aide (il fait un peu de travail autrement répétitif), et pourtant être en mesure d'utiliser using?

Répondre

13

Une façon est de changer de retourner une commande pour prendre un délégué qui utilise la commande:

protected void ExecuteSproc(string name, 
          SqlDbType? returnType, 
          Action<SqlCommand> action) 
{ 
    using (SqlConnection con = new SqlConnection(this.ConnectionString)) 
    using (SqlCommand com = new SqlCommand(name, con)) 
    { 
     con.Open(); 
     com.CommandType = System.Data.CommandType.StoredProcedure; 

     if (returnType != null) 
     { 
      com.Parameters.Add("ReturnValue", returnType.Value).Direction = 
       ParameterDirection.ReturnValue; 
     } 
     action(com); 
    } 
} 

(Notez que j'ai aussi enlevé le paramètre includeReturn et fait Null à la place. Il suffit de passer null pour "aucune valeur de retour".)

Vous utiliseriez ceci avec une expression lambda (ou méthode anonyme):

ExecuteSproc("SomeName", SqlDbType.DateTime, cmd => 
{ 
    // Do what you want with the command (cmd) here 
}); 

De cette façon, la disposition est au même endroit que la création et l'appelant ne fonctionne tout simplement pas besoin de se soucier. Je deviens un fan de ce modèle - il est beaucoup plus propre maintenant que nous avons des expressions lambda.

+1

Vraiment sympa! :-) –

+1

Il est probablement logique d'ouvrir la connexion en tant qu'effet secondaire dans cette instance ... (puisqu'il est fermé en tant qu'effet secondaire) –

+0

@ sambo99: Yup, va éditer. –

0

Que diriez-vous:

using (SqlCommand cmd = CreateSprocCommand("whatever")) 
{ 
    cmd.Connection.Open(); 
    using (var reader = cmd.ExecuteReader()) 
    { 
    //blabla 
    } 
} 
+2

Je ne pense pas que la disposition de la commande disposera de la connexion –

+0

sambo99 est juste, je vérifie que dans le réflecteur – Gidon

+0

Est-ce que cmd.Dispose() appelle cmd.Connection.Dispose()? –

1

Vous pouvez imbriquer en utilisant des déclarations:

using (SqlCommand cmd = CreateSprocCommand("...")) 
{ 
    using (var connection = cmd.Connection) 
    { 
    connection.Open(); 
    using (var reader = cmd.ExecuteReader()) 
    { 
     ... 
    } 
    ... 
    } 
} 
+0

J'omets habituellement les accolades de bloc des niveaux externes et je les indent au même niveau pour communiquer que j'ai l'intention que tous les objets jetables ainsi formatés soient utilisés ensemble. Je n'ai pas encore décidé si c'est une mauvaise idée ou une très mauvaise idée ;-) – Rytmis

-1

Est-ce que vous voulez dire?

using (SqlCommand cmd = CreateSprocCommand("SomeSprocName")) 
{ 
    cmd.Connection.Open(); 
    using (var reader = cmd.ExecuteReader()) 
    { 
     //some code looping over the recors 
    } 
} 
+0

Comme Rune, cela ne fermerait pas la connexion. – Gidon

3

Vous pouvez le faire:

protected static SqlCommand CreateSprocCommand(SqlConnection con, string name, bool includeReturn, SqlDbType returnType) 
{ 
    SqlCommand com = new SqlCommand(name, con); 
    com.CommandType = System.Data.CommandType.StoredProcedure; 

    if (includeReturn) 
     com.Parameters.Add("ReturnValue", returnType).Direction = ParameterDirection.ReturnValue; 

    return com; 
} 

et l'appeler comme ceci:

using (SqlConnection con = new SqlConnection(this.ConnectionString)) 
using (SqlCommand cmd = CreateSprocCommand(con, "SomeSprocName", true, SqlDbType.Int) 
{ 
    cmd.Connection.Open(); 
    using (var reader = cmd.ExecuteReader()) 
    { 
     //some code looping over the recors 
    } 
    //some more code to return whatever needs to be returned 
} 
+0

Aha, donc je ne suis pas le seul à formater des utilisations imbriquées comme ça! – Rytmis

Questions connexes