#c# #sql #stored-procedures #parameters #sqldataadapter
Вопрос:
У меня есть этот код, запущенный в событии form_load:
using (SqlConnection sqlConn = new SqlConnection(strConn))
{
sqlConn.Open();
SqlDataAdapter sqlDa = new SqlDataAdapter("pp_sp_MachineAndOp", sqlConn);
DataTable sqlDt = Helper.ExecuteDataTable("pp_sp_MachineAndOp", new SqlParameter("@MachineAndOpID", 7));
sqlDa.Fill(sqlDt);
dgvMachineAndOp.AutoGenerateColumns = false;
dgvMachineAndOp.DataSource = sqlDt;
sqlDa.Dispose();
sqlConn.Close();
}
Я получаю ошибку «Процедура или функция «pp_sp_MachineAndOp» ожидает параметр «@MachineAndOpID», который не был указан». в строке:
sqlDa.Fill(sqlDt);
Важно отметить, что если я открою визуализатор данных sqlDt во время выполнения, я увижу ожидаемые результаты!
Вот код, стоящий за помощником.Выполнимо:
public static DataTable ExecuteDataTable(string storedProcedureName, params SqlParameter[] arrParam)
{
DataTable dt = new DataTable();
// Open the connection
using (SqlConnection sqlConn = new SqlConnection(strConn))
{
try
{
sqlConn.Open();
// Define the command
using (SqlCommand sqlCmd = new SqlCommand())
{
sqlCmd.Connection = sqlConn;
sqlCmd.CommandType = CommandType.StoredProcedure;
sqlCmd.CommandText = storedProcedureName;
// Handle the parameters
if (arrParam != null)
{
foreach (SqlParameter param in arrParam)
{
sqlCmd.Parameters.Add(param);
}
}
// Define the data adapter and fill the dataset
using (SqlDataAdapter da = new SqlDataAdapter(sqlCmd))
{
da.Fill(dt);
}
}
}
catch (SqlException ex)
{
MessageBox.Show(ex.Message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
return dt;
}
Чего мне не хватает?
Комментарии:
1.
Helper.ExecuteDataTable
это пользовательский код, мы не можем сказать вам, что с ним не так на расстоянии. Я скажу, что это очень подозрительно, что вам нужно упомянутьpp_sp_MachineAndOp
дважды, один раз в конструкторе дляSqlDataAdapter
, а затем еще раз в помощнике. При правильном дизайне не было бы необходимости повторять это. Я подозреваю, чтоHelper.ExecuteDataTable
это предназначено для выполнения всей работы, и вообще нет необходимости привлекатьSqlDataAdapter
А.2. Я добавил код за помощником. Выполнимо.
3. Как вы можете видеть,
Helper.ExecuteDataTable
действительно выполняет всю работу , которую вамsqlDt
предстоит выполнить, в комплекте со своей собственнойSqlDataAdapter
. Почему вы используете свой собственный? Все, что вам нужно, — этоDataTable sqlDt = Helper.ExecuteDataTable("pp_sp_MachineAndOp", new SqlParameter("@MachineAndOpID", 7));
и ничего больше.
Ответ №1:
Удалите все, кроме
DataTable sqlDt = Helper.ExecuteDataTable("pp_sp_MachineAndOp", new SqlParameter("@MachineAndOpID", 7));
dgvMachineAndOp.AutoGenerateColumns = false;
dgvMachineAndOp.DataSource = sqlDt;
твой Помощник.ExecuteDataTable делает все. вам не нужно повторять то же самое в своем коде.
Ответ №2:
Я думаю, что ваш вспомогательный класс создает соединение с базой данных, поскольку в вашей таблице данных есть данные.
Итак, попробуйте удалить сохраненное имя процесса и объект подключения из адаптера, а затем проверьте.
SqlDataAdapter sqlDa = новый SqlDataAdapter();//используйте только это.
Комментарии:
1. Я попробовал это, и теперь я получаю ошибку: «Свойство SelectCommand не было инициализировано перед вызовом «Заполнить». » Я добавлю помощника. Выполнимый код за несколько минут.
Ответ №3:
вы можете использовать нижеприведенную функцию(требуется модификация в соответствии с вашими потребностями):
public IDataReader ExecuteReader(string spName, object[] parameterValues)
{
command = GetCommand();
command.CommandType = CommandType.StoredProcedure;
command.CommandText = spName;
if (parameterValues != null)
{
for (int i = 0; i < parameterValues.Length; i )
{
command.Parameters.Add(parameterValues[i]);
}
}
reader = command.ExecuteReader();
if (parameterValues != null)
command.Parameters.Clear();
return reader;
}