SqlConnection con = new SqlConnection(constr);
SqlCommand cmd = new SqlCommand("insert into reg (name,num,gender,qual) values
(#name,#num,#gender,#qual)", con);
cmd.Parameters.AddWithValue("#name", TextBox1.Text);
cmd.Parameters.AddWithValue("#num", TextBox2.Text);
cmd.Parameters.AddWithValue("#gender",
RadioButtonList1.SelectedItem.ToString());
for (int i = 0; i < CheckBoxList1.Items.Count - 1;i++ )
{
if(CheckBoxList1.Items[1].Selected)
{
string var = string.Empty;
var += CheckBoxList1.Items[1].Text.ToString();
cmd.Parameters.AddWithValue("#qual",var);
}
}
try
{
con.Open();
cmd.ExecuteNonQuery();
Response.Write("<script language='javascript'>alert(
'record has been added');</script>");
}
catch (Exception er)
{
Response.Write("<script language='javascript'>alert(
'conncetion error');</script>");
}
finally
{
con.Close();
}
I am beginner of asp.net. I don't know how to save the checkboxlist values to data base. I the above code it saves only the last value. Please help me, thanks in advance...
You are iterating through loop but only comparing value 1 all the time I have changed 1 to i.
And I think you need to collect values and and them all only once.To perfoem that I have moved cmd.Parameters.AddWithValue("#qual",s); statement out of for loop
Note: I am separating values with ',' I don't know that is your business need or not
string s;
for (int i = 0; i < CheckBoxList1.Items.Count - 1;i++ )
{
if(CheckBoxList1.Items[i].Selected)//changed 1 to i
s += CheckBoxList1.Items[i].Text.ToString() + ","; //changed 1 to i
}
cmd.Parameters.AddWithValue("#qual",s);
It's because you're only executing the command once, outside of the for-loop.
If you move the Execute query into the for loop it should work.
Note that this will fix your code, but it will neither safe or optimal.
Related
I have this method which inserts data to two different tables in my database from textboxes and Datagridview , The first insert query executing normally but the second one throws an error
Object reference not set to an instance of an object
Here is my method:
private void InsertAll()
{
DialogResult Result = MessageBox.Show("Do you want to save all ? ", "Warnning", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
if (Result == DialogResult.OK)
{
using (SqlCommand cmd = new SqlCommand())
{
try
{
cmd.Connection = Cn;
cmd.CommandType = CommandType.Text;
Cn.Open();
// Insert the header first Due to one-to-many relationship
cmd.CommandText = #" INSERT INTO DocDtls ( DocNum, zDate, Warehouse, Orientation,TransType,UserName )
VALUES (#prm1, #prm2, #prm3, #prm4, #prm5, #prm6);";
cmd.Parameters.AddWithValue("#prm1", txtDocNum.Text);
cmd.Parameters.AddWithValue("#prm2", txtDate.Value.ToString("yyyy-MM-dd"));
cmd.Parameters.AddWithValue("#prm3", cmbWh.Text);
cmd.Parameters.AddWithValue("#prm4", txtOrient.Text);
cmd.Parameters.AddWithValue("#prm5", txtTransType.Text);
cmd.Parameters.AddWithValue("#prm6", txtUser.Text);
cmd.ExecuteNonQuery();
// Insert the Details >> where the problem start to occur
if (txtTransType.Text == "Release")
{
cmd2.Connection = Cn;
cmd2.CommandType = CommandType.Text;
// Cn.Open();
for (int i = 0; i < DGV1.Rows.Count; i++)
{
cmd2.CommandText = #"INSERT INTO Transactions ( DocNum, Code, QtyIn, QtyOut, BalanceAfter, Remarks, Unit)
VALUES (#prm1, #prm2, #prm3, #prm4, #prm5, #prm6,#prm7);";
cmd2.Parameters.AddWithValue("#prm1", txtDocNum.Text);
cmd2.Parameters.AddWithValue("#prm2", DGV1.Rows[i].Cells["Code"].Value);
cmd2.Parameters.AddWithValue("#prm3", 0);
cmd2.Parameters.AddWithValue("#prm4", DGV1.Rows[i].Cells["Qty"].Value);
cmd2.Parameters.AddWithValue("#prm5", DGV1.Rows[i].Cells["BalanceAfter"].Value);
cmd2.Parameters.AddWithValue("#prm6", DGV1.Rows[i].Cells["Remarks"].Value);
cmd2.Parameters.AddWithValue("#prm7", DGV1.Rows[i].Cells["Unit"].Value);
cmd2.ExecuteNonQuery();
MessageBox.Show("Registered", "Done", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
else
{
cmd2.Connection = Cn;
cmd2.CommandType = CommandType.Text;
//Cn.Open();
for (int i = 0; i < DGV1.Rows.Count; i++)
{
cmd2.CommandText = #"INSERT INTO Transactions ( DocNum, Code, QtyIn, QtyOut, BalanceAfter, Remarks, Unit )
VALUES (#prm1, #prm2, #prm3, #prm4, #prm5, #prm6,#prm7);";
cmd2.Parameters.AddWithValue("#prm1", txtDocNum.Text);
cmd2.Parameters.AddWithValue("#prm2", DGV1.Rows[i].Cells["Code"].Value);
cmd2.Parameters.AddWithValue("#prm3", DGV1.Rows[i].Cells["Qty"].Value);
cmd2.Parameters.AddWithValue("#prm4", 0);
cmd2.Parameters.AddWithValue("#prm5", DGV1.Rows[i].Cells["BalanceAfter"].Value);
cmd2.Parameters.AddWithValue("#prm6", DGV1.Rows[i].Cells["Remarks"].Value);
cmd2.Parameters.AddWithValue("#prm7", DGV1.Rows[i].Cells["Unit"].Value);
cmd2.ExecuteNonQuery();
MessageBox.Show("Registered", "Done", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}
catch (Exception e)
{
MessageBox.Show(e.Message.ToString(), "Error Message",MessageBoxButtons.OK,MessageBoxIcon.Error);
}
Cn.Close();
}
}
}
I suspected that the connection might be closed in some point so I added opening connection again after the first insert but the problem still happening.
What's wrong with my code?
Thanks in advance
Try this. There's a lot of code, so likely a typo or other issue or two still here. Pay attention to the comments:
private void InsertAll()
{
using (var cn = new SqlConnection(Cn.ConnectionString)) // Using block around the connection
using (var cmd = new SqlCommand("", cn))
{
//removed the try/catch. Instead, wrap the try/catch around this method call
cmd.CommandText = #" INSERT INTO DocDtls ( DocNum, zDate, Warehouse, Orientation,TransType,UserName )
Values (#prm1, #prm2, #prm3, #prm4, #prm5, #prm6);";
//AddWithValue() can be dangerously slow, but usually still safe for single simple INSERT
cmd.Parameters.AddWithValue("#prm1", txtDocNum.Text);
cmd.Parameters.AddWithValue("#prm2", txtDate.Value); //If you're converting a DateTime to a string for use in SQL, you're doing something VERY WRONG
cmd.Parameters.AddWithValue("#prm3", cmbWh.Text);
cmd.Parameters.AddWithValue("#prm4", txtOrient.Text);
cmd.Parameters.AddWithValue("#prm5", txtTransType.Text);
cmd.Parameters.AddWithValue("#prm6", txtUser.Text);
cn.Open(); //Wait until last possible moment to call cn.Open()
cmd.ExecuteNonQuery();
// Normally don't re-use the same connection, but
// within a single operation context like this it's okay
// not only for the connection, but for the command, too.
cmd.CommandText = #" INSERT INTO Transactions ( DocNum, Code, QtyIn, QtyOut, BalanceAfter, Remarks, Unit )
Values (#DocNum, #Code, #QtyIn, #QtyOut, #BalanceAfter, #Remarks,#Unit);";
cmd.Parameters.Clear(); //Missing this line is why you had to create cmd2 before.
// Use exact types from the database here. Don't let ADO.Net try to infer these.
cmd.Parameters.Add("#DocNum", SqlDbType.VarChar, 10).Value = txtDocNum.Text;
cmd.Parameters.Add("#Code", SqlDbType.Char, 7);
// the "= 0" at the end of the next two lines are important.
cmd.Parameters.Add("#QtyIn", SqlDbType.Int).Value = 0;
cmd.Parameters.Add("#QtyOut", SqlDbType.Int).Value = 0;
cmd.Parameters.Add("#BalanceAfter", SqlDbType.Decimal);
cmd.Parameters.Add("#Remarks", SqlDbType.NVarChar, 1000);
cmd.Parameters.Add("#Unit", SqlDbType.NVarChar, 10);
// We can also set the Qty switch outside the loop
var qtyKey = (txtTransType.Text == "Release")?"#QtyOut":"#QtyIn";
for (int i = 0; i < DGV1.Rows.Count; i++)
{
// Only change parameter values inside the loop
cmd.Parameters["#Code"] = DGV1.Rows[i].Cells["Code"].Value;
cmd.Parameters[qtyKey].Value = DGV1.Rows[i].Cells["Qty"].Value;
cmd.Parameters["#BalanceAfter"] = DGV1.Rows[i].Cells["BalanceAfter"].Value;
cmd.Parameters["#Remarks"] = DGV1.Rows[i].Cells["Remarks"].Value;
cmd.Parameters["#Unit"] = DGV1.Rows[i].Cells["Unit"].Value;
cmd.ExecuteNonQuery();
}
// No need to call cn.Close(). Using blocks take care of it.
}
}
Note I removed the initial prompt/check, the try/catch, and the final complete message. Those things belong with the caller, like this:
DialogResult Result = MessageBox.Show("Do you want to save all ? ", "Warning", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
if (Result == DialogResult.OK)
{
try
{
InsertAll()
MessageBox.Show("Registered", "Done", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch(Exception e)
{
MessageBox.Show(e.Message.ToString(), "Error Message",MessageBoxButtons.OK,MessageBoxIcon.Error);
}
}
Eventually you would also move the method (and other database access) be a static member of a separate class, where the required information is passed as arguments.
I'm having two mysql TABLES - ORDER and ORDER_DETAILS the relationship is one order has many order_details.
After creating an order, I get the last inserted id and I need to insert order details with last inserted last order id via a for loop. But here it is showing a message
#order_id has already been defined
when having more than one order details. If it is one order detail it works.
How can I defined this order id here? Is this a wrong way? Here is my code:
private void button2_Click(object sender, EventArgs e)
{
try
{
DateTime localDate = DateTime.Now;
MydbConnection db = new MydbConnection();
MySqlConnection con = db.connection();
MySqlCommand cmd = new MySqlCommand();
cmd.CommandText = "insert into orders (created) values(#localDate)";
cmd.Parameters.AddWithValue("#localDate", localDate);
cmd.Connection = con;
con.Open();
cmd.ExecuteNonQuery();
long lastId = cmd.LastInsertedId;//Last inserted id
for (int i = 0; i < listView3.Items.Count; i++)
{
cmd.CommandText = "insert into order_details (order_id,product_id,qty) values(#order_id,#product_id,#qty)";
cmd.Parameters.AddWithValue("#order_id", lastId);
cmd.Parameters.AddWithValue("#product_id", 1);
cmd.Parameters.AddWithValue("#qty", listView3.Items[i].SubItems[1]);
cmd.ExecuteNonQuery();
}
}
catch (Exception es) {
MessageBox.Show("Order not saved! "+es.Message);
}
}
Each time you call cmd.Parameters.AddWithValue you adding one more parameters. When you call it twice or more with parameter with same name duplicated parameters appears.
When your listView3.Items.Count contains at least two elements, your code will add duplicated #order_id, #product_id and #qty.
You need either to recreate your MySqlCommand cmd on each iteration, or change value of parameters when they already added.
First approach is more error-prone. Al least because you will not use other data left from previous usage (#localDate parameter you adding before loop, that otherwise will be also passed to database).
for (int i = 0; i < listView3.Items.Count; i++)
{
cmd = new MySqlCommand();
cmd.Connection = con;
cmd.CommandText = "insert into order_details (order_id,product_id,qty) values(#order_id,#product_id,#qty)";
cmd.Parameters.AddWithValue("#order_id", lastId);
cmd.Parameters.AddWithValue("#product_id", 1);
cmd.Parameters.AddWithValue("#qty", listView3.Items[i].SubItems[1]);
cmd.ExecuteNonQuery();
}
You can't keep adding the same command parameters over and over. Instead, why not re-use them:
private void button2_Click(object sender, EventArgs e)
{
try
{
DateTime localDate = DateTime.Now;
MydbConnection db = new MydbConnection();
MySqlConnection con = db.connection();
MySqlCommand cmd = new MySqlCommand();
cmd.CommandText = "insert into orders (created) values(#localDate)";
cmd.Parameters.AddWithValue("#localDate", localDate);
cmd.Connection = con;
con.Open();
cmd.ExecuteNonQuery();
long lastId = cmd.LastInsertedId;//Last inserted id
cmd.CommandText = "insert into order_details (order_id,product_id,qty) values(#order_id,#product_id,#qty)";
MySqlCommandParameter orderIdParam, productIdParam, qtyParam;
for (int i = 0; i < listView3.Items.Count; i++)
{
if (i == 0)
{
orderIdParam = cmd.Parameters.AddWithValue("#order_id", lastId);
productIdParam = cmd.Parameters.AddWithValue("#product_id", 1);
qtyParam = cmd.Parameters.AddWithValue("#qty", listView3.Items[i].SubItems[1]);
}
else
{
orderIdParam.Value = lastId;
productIdParam.Value = 1;
qtyParam.Value = listView3.Items[i].SubItems[1];
}
cmd.ExecuteNonQuery();
}
}
catch (Exception es) {
MessageBox.Show("Order not saved! "+es.Message);
}
}
Note: I haven't actually tested this code and probably have the wrong types and member names for MySqlCommandParameter and MySqlCommandParameter.Value but you should still get the idea.
It would probably be better coding practice to Add the parameters first (before entering the loop) and not have the if block in the loop instead of using AddWithValue for the first loop iteration. You could also think about Clear-ing the parameter collection on the command and calling AddWithValue every iteration. Ultimately, I think it is best to re-use the parameters, though - certainly preferable to creating a new instance of MySqlCommand every iteration - there might be thousands of iterations!
Firstly, as hinted in the comments, you need a way to remove the parameters added in the previous iteration of the loop:
cmd.Parameters.Clear();
placed after cmd.ExecuteNonQuery() will do that for you. But beware! The SQL connection, and the SQL command, .NET base types implement IDisposable, and you should despose of them properly when you're done with them to avoid things like connection pool blocking. I've recently had to rescue an old project from poorly managed disposables and a) it was a pain but b) the result was a much faster, more reliable app. You might want to look in to that when you've solved your current problem.
I have a program where I open a SqlConnection, load up a list of objects, modify a value on each object, then update the rows in the SQL Server database. Because the modification requires string parsing I wasn't able to do with with purely T-SQL.
Right now I am looping through the list of objects, and running a SQL update in each iteration. This seems inefficient and I'm wondering if there is a more efficient way to do it using LINQ
The list is called UsageRecords. The value I'm updating is MthlyConsumption.
Here is my code:
foreach (var item in UsageRecords)
{
string UpdateQuery = #"UPDATE tbl810CTImport
SET MthlyConsumption = " + item.MthlyConsumption +
"WHERE ID = " + item.Id;
SqlCommand update = new SqlCommand(UpdateQuery, sourceConnection);
update.ExecuteNonQuery();
}
Try this instead:
string UpdateQuery = #"UPDATE tbl810CTImport SET MthlyConsumption = #consumption WHERE ID = #itemId";
var update = new SqlCommand(UpdateQuery, sourceConnection);
update.Parameters.Add("#consumption", SqlDbType.Int); // Specify the correct types here
update.Parameters.Add("#itemId", SqlDbType.Int); // Specify the correct types here
foreach (var item in UsageRecords)
{
update.Parameters[0].Value = item.MthlyConsumption;
update.Parameters[1].Value = item.Id;
update.ExecuteNonQuery();
}
It should be faster because:
You don't have to create the command each time.
You don't create a new string each time (concatenation)
The query is not parsed at every iteration (Just changes the parameters values).
And it will cache the execution plan. (Thanks to #JohnCarpenter from the comment)
You can either use
SqlDataAdapter - See How to perform batch update in Sql through C# code
or what I have previously done was one of the following:
Tear down the ID's in question, and re-bulkinsert
or
Bulk Insert the ID + new value into a staging table, and update the table on SQL server:
update u
set u.MthlyConsumption = s.MthlyConsumption
from tbl810CTImport u
inner join staging s on
u.id = s.id
In a situation like this, where you can't write a single update statement to cover all your bases, it's a good idea to batch up your statements and run more than one at a time.
var commandSB = new StringBuilder();
int batchCount = 0;
using (var updateCommand = sourceConnection.CreateCommand())
{
foreach (var item in UsageRecords)
{
commandSB.AppendFormat(#"
UPDATE tbl810CTImport
SET MthlyConsumption = #MthlyConsumption{0}
WHERE ID = #ID{0}",
batchCount
);
updateCommand.Parameters.AddWithValue(
"#MthlyConsumption" + batchCount,
item.MthlyConsumption
);
updateCommand.Parameters.AddWithValue(
"#ID" + batchCount,
item.MthlyConsumption
);
if (batchCount == 500) {
updateCommand.CommandText = commandSB.ToString();
updateCommand.ExecuteNonQuery();
commandSB.Clear();
updateCommand.Parameters.Clear();
batchCount = 0;
}
else {
batchCount++;
}
}
if (batchCount != 0) {
updateCommand.ExecuteNonQuery();
}
}
It should be as simple as this . . .
private void button1_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection("Server=YourServerName;Database=YourDataBaseName;Trusted_Connection=True");
try
{
//cmd new SqlCommand( "UPDATE Stocks
//SET Name = #Name, City = #cit Where FirstName = #fn and LastName = #add";
cmd = new SqlCommand("Update Stocks set Ask=#Ask, Bid=#Bid, PreviousClose=#PreviousClose, CurrentOpen=#CurrentOpen Where Name=#Name", con);
cmd.Parameters.AddWithValue("#Name", textBox1.Text);
cmd.Parameters.AddWithValue("#Ask", textBox2.Text);
cmd.Parameters.AddWithValue("#Bid", textBox3.Text);
cmd.Parameters.AddWithValue("#PreviousClose", textBox4.Text);
cmd.Parameters.AddWithValue("#CurrentOpen", textBox5.Text);
con.Open();
int a = cmd.ExecuteNonQuery();
if (a > 0)
{
MessageBox.Show("Data Updated");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
con.Close();
}
}
Change the code to suit your needs.
I'm connected to a database through the SqlConnection class. Is there any simple why to check how many rows are in the database or do I have to create a SqlDataReader and increment till the last row in it ?
I assume "rows in the database" actually means "rows in the table".
You should use Count and SqlCommand.ExecuteScalar:
int rowCount = 0;
using(var con = new SqlConnection(connectionsString))
using (var cmd = new SqlCommand("SELECT COUNT(*) FROM dbo.TableName", con))
{
try
{
con.Open();
rowCount = (int) cmd.ExecuteScalar();
} catch (Exception ex)
{
// log this exception or do something else useful, otherwise it's better to...
throw;
}
}
what is wrong with this code what i am actually to achieve is
insert rows to database clear the textbox value and enter another record..
the problem is at first loop data will be added successfully...but on the next iteration loops it will add empty strings to the rows of database but what i want is accept input from textbox and continue iterating...please try to read the code and help me ...it is been 2 weeks since am trying so solve this ..
again what i want to do
-user enter number of group members
- the group members have column like ,first name,last name gender,city.etc
FOR all the group members (eg:6 group membrs) add 6 rows of of different column will be added
but my code does is add the first rows and the rest 5 row's will be empty data
Sorry for my bad english..somebody please try to think what i am thinking
{{
private void btnAddloan_Click(object sender, RoutedEventArgs e)
if (txtname.Text != "" && txtlname.Text != "")
{
int c=0;
int input=int.Parse(txttotalnumberofgroupmembers.Text);
do
{
string connstr = "Data Source=GER-PC\\PLEASEGOD;Initial Catalog=ACSI;Integrated Security=True";
SqlConnection con = new SqlConnection(connstr);
con.Open();
SqlCommand cmd = new SqlCommand("insert into Customer(FirstName,LastName) values(#n,#p)", con);
cmd.Parameters.AddWithValue("#p", txtname.Text);
cmd.Parameters.AddWithValue("#n", txtlname.Text);
cmd.ExecuteNonQuery();
con.Close();
lblnotify.Content = c + 1 + "" + "members added";
//clear textbox values and wait for another input
txtname.Text = "";
txtlname.Text = "";
if (txtname.Text != "" && txtlname.Text != "")
{
continue;
}
else
{
MessageBoxResult result =MessageBox.Show("procces","Continue Adding Memebers",MessageBoxButton.YesNoCancel,MessageBoxImage.Warning);
//txtname.Text = s;
//txtlname.Text= s1;
//MessageBox.Show();
switch (result)
{
case MessageBoxResult.Yes:
if (txtname.Text != "")
{
}
else
{
}
break;
case MessageBoxResult.No:
break;
case MessageBoxResult.Cancel:
break;
}
}
c++;
} while (c < input);
}
else
{
MessageBox.Show("plese fill first name and last name");
}
}
You're clearing the txtname.Text and txtlname.Text value after you do the insert. In the next iteration you're recreating the Parameters, but this time your text values are EMPTY.
txtname.Text = "";
txtlname.Text = "";
Instead of recreating your command object, why not just execute the command object N times. Like:
SqlCommand cmd = new SqlCommand("insert into Customer(FirstName,LastName) values(#n,#p)", con);
cmd.Parameters.AddWithValue("#p", txtname.Text);
cmd.Parameters.AddWithValue("#n", txtlname.Text);
for(int i = 0; i < input; i++)
{
cmd.ExecuteNonQuery();
}