Будет ли выполнение SqlCommand полностью спорным и избыточным и замедлит ли это работу?
Благодаря некоторым советам и напоминаниям, я изменил свой код из этого грязного беспорядка:
try
{
DataSet dsUsage = new DataSet();
SqlConnection conn = new SqlConnection("SERVER=PROSQL05;DATABASE=platypusdata;UID=duckbill;PWD=poisonToe42;Connection Timeout=0");
SqlDataAdapter da = new SqlDataAdapter();
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = String.Format("Exec sp_ViewProductUsage_MappingRS '{0}', '{1}', '{2}'", mammal, dateBegin, dateEnd);
da.SelectCommand = cmd;
conn.Open();
da.Fill(dsUsage);
conn.Close();
DataTable dtUsage = dsUsage.Tables[0];
if (dtUsage.Rows.Count > 0)
{
foreach (DataRow productUsageByMonthDataRow in dtUsage.Rows)
{
. . .
...к этому:
try
{
SqlDataAdapter da = new SqlDataAdapter();
DataSet dsUsage = new DataSet();
using (SqlConnection conn = new SqlConnection(UsageRptConstsAndUtils.PlatypusConnStr))
{
using (SqlCommand cmd = new SqlCommand("sp_ViewProductUsage_MappingRS", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@Unit", SqlDbType.VarChar).Value = _unit;
cmd.Parameters.Add("@BegDate", SqlDbType.DateTime).Value = dtBegin;
cmd.Parameters.Add("@EndDate", SqlDbType.DateTime).Value = dtEnd;
da.SelectCommand = cmd;
conn.Open();
//cmd.ExecuteReader(); <- Is this even necessary?
da.Fill(dsUsage);
}
}
DataTable dtUsage = dsUsage.Tables[0];
if (dtUsage.Rows.Count > 0)
{
// Populate the cells
foreach (DataRow productUsageByMonthDataRow in dtUsage.Rows)
{
. . .
Обратите внимание, что у меня есть SqlCommand
"s ExecuteReader
закомментировано в новом коде, потому что это кажется ненужным из-за SqlDataAdapter
будучи обеспеченным SqlCommand
, Работает нормально. Итак: я прав, если я могу удалить cmd.ExecuteReader()
вообще? Есть ли какое-то преимущество в его сохранении, или это будет полностью излишним и создаст "занятую работу" для процесса?
ОБНОВИТЬ
Итак, чтобы передать массив SqlParameter (методу ExecuteDataSet в ответе MethodMan), я понимаю, что сначала мне нужно будет сделать что-то вроде:
SqlParameter sqlp = new SqlParameter();
sqlp.ParameterName = "Unit";
sqlp.Value = _unit;
cmd.Parameters.Add(sqlp);
...так далее. (а затем добавить их в массив - или, возможно, лучше общий список SqlParameter).
ОБНОВЛЕНИЕ 2
Я просто столкнулся с этим в первый раз: если вы используете пример MethodMan (который я делаю), и вы используете запрос без параметров, вам нужно обойти цикл добавления параметров следующим образом:
if (null != parameters)
{
foreach (var item in parameters)
{
cmd.Parameters.Add(item);
}
}
1 ответ
Я лично создал бы класс SqlDBHelper и передал бы вызов хранимой процедуры, используя такой метод, как этот
public static class SqlDBHelper
{
public static DataSet ExecuteDataSet(string sql, CommandType cmdType, params SqlParameter[] parameters)
{
using (DataSet ds = new DataSet())
using (SqlConnection connStr = new SqlConnection(ConfigurationManager.ConnectionStrings["DbConn"].ConnectionString))
using (SqlCommand cmd = new SqlCommand(sql, connStr))
{
cmd.CommandType = cmdType;
foreach (var item in parameters)
{
cmd.Parameters.Add(item);
}
try
{
cmd.Connection.Open();
new SqlDataAdapter(cmd).Fill(ds);
}
catch (SqlException ex)
{
//log to a file or write to Console for example
Console.WriteLine(ex.Message);
}
return ds;
}
}
}
Если вы хотите вернуть DataTable, измените тип возвращаемого значения в сигнатуре метода и вызовите следующее в приведенном ниже операторе возврата.
public static DataTable ExecuteDataSet(string sql, CommandType cmdType, params SqlParameter[] parameters)
return ds.Tables[0];
Вот пример того, как вы бы назвали метод
someDataTable = SqlDBHelper.ExecuteDataSet("sp_ViewProductUsage_MappingRS", CommandType.StoredProcedure,
new SqlParameter() { ParameterName = "@Unit", SqlDbType = SqlDbType.VarChar, Value = _unit },
new SqlParameter() { ParameterName = "@BegDate", SqlDbType = SqlDbType.DateTime, Value = dtBegin },
new SqlParameter() { ParameterName = "@EndDate", SqlDbType = SqlDbType.DateTime, Value = dtEnd }
);