Рефакторинг кода в оператор using
-
05-09-2019 - |
Вопрос
У меня есть слой dal с множеством методов, все они вызывают хранимые процедуры, некоторые списки возврата (поэтому с использованием SqlDataReader
), другие только определенное значение.
У меня есть вспомогательный метод, который создает 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;
}
Теперь мое среднее (чрезмерно упрощенное) тело метода выглядит так:
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();
}
Есть ли способ реорганизовать это, чтобы я не потерял свою вспомогательную функцию (она выполняет довольно много повторяющейся работы), и при этом иметь возможность использовать using
?
Решение
Один из способов — изменить его с возвращение команда, чтобы принимая делегат, который использует команду:
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);
}
}
(Обратите внимание, что я также удалил includeReturn
параметр и сделал returnType
вместо этого имеет значение null.Просто пройди null
для «нет возвращаемого значения».)
Вы можете использовать это с лямбда-выражением (или анонимным методом):
ExecuteSproc("SomeName", SqlDbType.DateTime, cmd =>
{
// Do what you want with the command (cmd) here
});
Таким образом, удаление происходит в том же месте, что и создание, и вызывающему объекту просто не нужно об этом беспокоиться.Я становлюсь большим поклонником этого шаблона — теперь, когда у нас есть лямбда-выражения, он стал намного чище.
Другие советы
Вы можете сделать это:
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;
}
и назовите это так:
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
}
Вы можете вкладываться с помощью операторов:
using (SqlCommand cmd = CreateSprocCommand("..."))
{
using (var connection = cmd.Connection)
{
connection.Open();
using (var reader = cmd.ExecuteReader())
{
...
}
...
}
}
Как насчет:
using (SqlCommand cmd = CreateSprocCommand("whatever"))
{
cmd.Connection.Open();
using (var reader = cmd.ExecuteReader())
{
//blabla
}
}
Ты это имеешь ввиду ?
using (SqlCommand cmd = CreateSprocCommand("SomeSprocName"))
{
cmd.Connection.Open();
using (var reader = cmd.ExecuteReader())
{
//some code looping over the recors
}
}