Вставка данных несколько раз в таблицу SQL из одной кнопки в Windows Forms
я вставляю данные из Windows Forms форма в базу данных SQL, как показано ниже:
public partial class Form1 : Form
{
SqlConnection c = new SqlConnection();
string q = "Trusted_Connection = true; ";
public Form1()
{
InitializeComponent(); c.ConnectionString = q;
MessageBox.Show("Connecting Database");
}
private void button1_Click(object sender, EventArgs e)
{
string w = "insert into checkmultiuser(username) values (@username)";
SqlCommand cmd = new SqlCommand(w, c);
cmd.Parameters.Add("@username", SqlDbType.VarChar);
cmd.Parameters["@username"].Value = textBox1.Text;
cmd.ExecuteReader();
}
но когда я снова нажимаю кнопку, он говорит: "с этой командой уже связан открытый DataReader, который должен быть закрыт первым.".
Как мне справиться с этим?
*обновление: * я изменил код события нажатия кнопки, как показано ниже:
private void button1_Click(object sender, EventArgs e)
{
**c.Open();**
string w = "insert into checkmultiuser(username) values (@username)";
SqlCommand cmd = new SqlCommand(w, c);
cmd.Parameters.Add("@username", SqlDbType.VarChar);
cmd.Parameters["@username"].Value = textBox1.Text;
//cmd.ExecuteNonQuery();
cmd.ExecuteReader();
**c.Close();**
}
каковы его недостатки? Один был бы таким снова и снова. опять соединение открывается и закрывается при нажатии кнопки.
4 ответов
читателю нужно открытое соединение, потому что вы извлекаете результаты по одному за раз. Вы захотите сделать ExecuteNonQuery () для вставок, удалений и обновлений. После этого Вам также нужно закрыть соединение. Альтернативой является обертывание вставок в цикл, если вы планируете сделать несколько вставок.
есть несколько способов сделать это. Этот способ полезен, если вы планируете повторно использовать один и тот же объект подключения и объект команды снова и снова опять:
public partial class Form1 : Form
{
SqlConnection _cn;
SqlCommand _cmd;
const string ConnString = "Enter your connection string here";
readonly string _insertQuery;
const string UsernameParm = "@username";
public Form1()
{
InitializeComponent();
_cn = new SqlConnection(ConnString);
_cmd = new SqlCommand(InsertQuery, _cn);
_cmd.Parameters.Add(UsernameParm, SqlDbType.VarChar);
_insertQuery = String.Format("INSERT INTO checkmultiuser(username) VALUES ({0})",
UsernameParm);
}
private void button1_Click(object sender, EventArgs e)
{
_cmd.Parameters[UsernameParm].Value = textBox1.Text;
try
{
_cn.Open();
_cmd.ExecuteNonQuery();
}
catch (Exception ex) // probably best to catch specific exceptions
{
// handle it
}
finally
{
_cn.Close();
}
}
}
просто не забудьте избавиться от объектов connection и command (когда форма закрывается или где-либо имеет смысл для вашего приложения).
использование блоков является более безопасной альтернативой, но они будут избавляться от объекта каждый раз (хотя соединения используют пул соединений по умолчанию):
public partial class Form1 : Form
{
const string ConnString = "Enter your connection string here";
readonly string _insertQuery;
const string UsernameParm = "@username";
public Form1()
{
InitializeComponent();
_insertQuery = String.Format("INSERT INTO checkmultiuser(username) VALUES ({0})",
UsernameParm);
}
private void button1_Click(object sender, EventArgs e)
{
using (var cn = new SqlConnection(ConnString))
{
using (var cmd = new SqlCommand(InsertQuery, cn))
{
cmd.Parameters.Add(UsernameParm, SqlDbType.VarChar);
cmd.Parameters[UsernameParm].Value = textBox1.Text;
cn.Open();
cmd.ExecuteNonQuery();
}
}
}
}
любая комбинация будет работать. Вы можете настроить соединение один раз и просто обернуть объект command в using блок. Я знаю, что некоторые люди не являются поклонниками вложенных блоков (так как за кулисами это try (try finally) наконец)).
что сказал Джейсон.
пока вы там, возможно, стоит немного изменить код на:
private void button1_Click(object sender, EventArgs e)
{
string w = "insert into checkmultiuser(username) values (@username)";
c.Open();
using (SqlCommand cmd = new SqlCommand(w, c))
{
cmd.Parameters.Add("@username", SqlDbType.VarChar);
cmd.Parameters["@username"].Value = textBox1.Text;
cmd.ExecuteNonQuery();
}
}
для обеспечения правильного удаления объектов.
может быть, положить его в try{}
блок тоже, и закройте соединение в finally{ c.Close();}
прежде всего, вы должны использовать ExecuteNonQuery
для обработки вставок, обновлений и удаления. ExecuteNonQuery используется, когда вы не ожидаете возврата значения из базы данных.
но если вы действительно хотите использовать DataReader в другой ситуации, вы должны использовать его, как показано ниже.
using (SqlDataReader reader= cmd.ExecuteReader())
{
while (reader.Read())
{
//Do the reading
}
}
Это гарантирует, что SqlDataReader
закрывается, как только намеченная работа выполнена.
другой потенциал исправить это установить MARS (несколько активных результирующих наборов) в правда в строке подключения.