Вставка сообщения не работает! Я пытаюсь вставить данные, используя параметры
System.Data.SqlClient.SqlException: «Имя переменной @name» уже объявлено. Имена переменных должны быть уникальными в пакете запросов или хранимой процедуре».
SqlCommand com = new SqlCommand();
public Form1()
{
InitializeComponent();
}
//save | event Click
private void btnSave_Click(object sender, EventArgs e)
{
if (txtName.Text == "" || txtLocation.Text == "")
{
MessageBox.Show("no data!","Hey you...",MessageBoxButtons.OK,MessageBoxIcon.Error);
}
else
{
com.Connection = con;
com.CommandText = "insert into Table_1 values ( @name ,@location )";
com.Parameters.AddWithValue("@name", txtName.Text);
com.Parameters.AddWithValue("@location", txtLocation.Text);
con.Open();
com.ExecuteNonQuery();
con.Close();
}
}
//clear fun
private void Clear()
{
txtName.Clear();
txtLocation.Clear();
}
}
}
}
Пожалуйста, прочтите Как задать вопрос и следуйте приведенным там советам о том, что делает вопрос хорошим.
У вас проблема с масштабом. Вы определяете SqlCommand com вне области, в которой вы его изменяете (т.е. добавляете в список параметров). По сути, вы добавляете параметр @name каждый раз, когда вызывается ваш метод btnSave_Click.
Переместите строку, в которой вы создаете com, в метод, чтобы она выглядела так:
SqlCommand com = new SqlCommand();
com.Connection = con;
com.CommandText = "insert into Table_1 values ( @name ,@location )";
com.Parameters.AddWithValue("@name", txtName.Text);
com.Parameters.AddWithValue("@location", txtLocation.Text);
con.Open();
com.ExecuteNonQuery();
con.Close();
И удалите SqlCommand com = new SqlCommand(); из верхней части кода.
Таким образом, команда создается заново каждый раз, когда запускается метод, и когда она создается заново, список параметров будет пустым, а строки, в которых вы добавляете параметры, не завершатся ошибкой.
РЕДАКТИРОВАТЬ Чтобы уточнить: проблема в том, что когда вы определяете это там, где вы это делаете, вам нужно добавлять параметры только один раз. Как «глобальная переменная» (на самом деле, в вашем коде она называется полем), такая как вы создаете, она создается только один раз, и это нормально. Проблема возникает, когда вы добавляете параметры в SqlCommand. Поскольку этот обработчик нажатия кнопки запускается каждый раз (я предполагаю), что нажимается кнопка, вы постоянно добавляете параметры в список. Первый раз, когда вы нажимаете кнопку, все в порядке, потому что в это время список параметров пуст. В следующий раз, когда вы нажмете кнопку, вы получите исключение, потому что в этот список уже добавлены эти параметры.
Если вы хотите продолжать использовать cmd в качестве глобальной переменной/поля, вам следует очистить список параметров в методе обработчика следующим образом:
com.Connection = con;
com.CommandText = "insert into Table_1 values ( @name ,@location )";
com.Parameters.clear();
com.Parameters.AddWithValue("@name", txtName.Text);
com.Parameters.AddWithValue("@location", txtLocation.Text);
con.Open();
com.ExecuteNonQuery();
con.Close();
SqlConnection должен использоваться в блоке использования или удаляться в конце метода.
@Оскар, хотя это хорошая (лучшая) практика, это не обязательно.
Спасибо @squillman, не могли бы вы дать мне больше объяснений. Я добавил SqlCommand com = new SqlCommand(); как глобальную переменную, поэтому я могу получить к ней доступ из любого места. так в чем тут проблема
@squillman важно ли добавить con.open(); в 1-й строке прицела или можно поставить где угодно внутри прицела, важна сортировка?
@Mohamed Смотрите мое редактирование. А по поводу открытия и закрытия соединения это вообще отдельная тема. Я не могу сказать, что тебе здесь лучше всего делать. Это зависит от множества других вещей, таких как сеть и то, как у вас структурированы другие части вашего кода.
@squillman Утилизация объектов — это больше, чем лучшая практика, поскольку невыполнение этого требования приведет к утечке памяти в вашем приложении.
@Oscar В общем, никаких реальных аргументов, но здесь это управляемый код, поэтому сборщик мусора его подберет. Это определенно лучшая практика в целом и требуется в определенных обстоятельствах, но с SqlConnection бывают случаи, когда вы намеренно повторно используете экземпляр, и в этом случае вы не хотите оборачивать его в using{} и вы избавляетесь от него в другом месте. Это хорошая привычка, но вы должны знать, когда ее использовать, а когда нет.
@squillman Нет, GC не может собирать неуправляемые объекты, созданные управляемыми классами, поэтому вы обязаны вызывать Dispose(). Если бы это было так просто, то не было бы смысла просить программистов вызывать Dispose(), так как сборщик мусора в конце концов очистил бы его сам. Что касается повторного использования соединений, я лично считаю это запахом кода и, вероятно, нарушением принципа единой ответственности.
@Оскар Это была моя точка зрения. SqlConnection — это управляемый код. Ваша точка зрения определенно резонирует с чем-то вроде COM-объекта. И тот факт, что SqlConnection МОЖЕТ содержать экземпляр чего-то, что не является управляемым кодом за кулисами, делает using лучшей практикой, потому что вы правы - в этом случае соединение не будет установлено сборщиком мусора, и вы есть утечка памяти. Я не согласен с вами в том, что повторное использование соединений может быть запахом кода. Итак, хотя using и является лучшей практикой, это не обязательно, и я добавлю: «Если вы знаете, что делаете!»
Вместо того, чтобы объявлять Connection как переменную класса, сделайте ее локальной переменной внутри обработчика кликов и поместите ее в блок using. В настоящее время вы добавляете один и тот же параметр при каждом нажатии кнопки.
using(var conn = new SqlConnection()){
//your code here
}
Пожалуйста, объясните, почему вы думаете, что «параметры не работают».