2009-05-26 9 views
1

Ich habe eine Dal-Ebene mit vielen Methoden, alle rufen gespeicherte Prozeduren, einige Rücksprunglisten (so mit einer Verwendung von SqlDataReader), andere nur einen bestimmten Wert.Refactor Code in die Verwendung der Anweisung

Ich habe eine Hilfsmethode, die die SqlCommand erstellt:

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

Jetzt ist mein Durchschnitt (übermäßig vereinfacht) Methode Körper wie folgt aussehen:

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

Gibt es eine Möglichkeit, um diese zu Refactoring, so dass Ich werde meine Hilfsfunktion nicht verlieren (es macht ziemlich viel sonst repetitive Arbeit), und kann doch using verwenden?

Antwort

13

Eine Möglichkeit ist es von zu ändern ein Befehl an Rückkehr einen Delegierten nehmen, die den Befehl verwendet:

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

(Beachten Sie, dass ich den includeReturn Parameter haben auch und entfernt gemacht returnType stattdessen Nullwert übergeben null für "kein Rückgabewert".)

Sie würden dies mit einem Lambda-Ausdruck (oder verwenden anonyme Methode):

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

diese Weise die Entsorgung in der gleichen Stelle wie die Schöpfung, und der Anrufer braucht nur nicht darum zu kümmern. Ich werde ein Fan von diesem Muster - es ist jetzt viel sauberer, wenn wir Lambda-Ausdrücke haben.

+1

Wirklich nett! :-) –

+1

Es macht wahrscheinlich Sinn, die Verbindung als Nebeneffekt in diesem Fall zu öffnen ... (da es als Nebeneffekt geschlossen wird) –

+0

@ sambo99: Yup, wird bearbeiten. –

0

Wie wäre:

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

Ich glaube nicht, dass Sie den Befehl Entsorgung wird die Verbindung –

+0

sambo99 ist richtig entsorgen, ich überprüft, dass in Reflector – Gidon

+0

Ruft cmd.Dispose() cmd.Connection.Dispose() auf? –

1

Sie können Nest mit Aussagen:

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

Normalerweise lasse ich die Block-Klammern von den äußeren Ebenen weg und ziehe sie auf die gleiche Ebene, um zu kommunizieren, dass ich beabsichtige, dass alle Einwegartikel, die auf diese Weise formatiert sind, zusammen verwendet werden. Ich habe mich noch nicht ganz entschieden, ob es eine schlechte Idee oder eine wirklich schlechte Idee ist ;-) – Rytmis

-1

Ist das, was Sie meinen?

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

Wie Rune, würde dies die Verbindung nicht schließen. – Gidon

3

Sie können dies tun:

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

und es so nennen:

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, also bin ich nicht der Einzige, der nested Usings so formatiert! – Rytmis