How do I display an error message if a student is already assigned with the position currently being inserted into the mysql database, then rollback the transaction?
If a different position is assigned, it should continue to check the next row.
Here is my code for insertion:
conn.Open();
MySqlTransaction mt = conn.BeginTransaction();
try {
for (int cnt = 0; cnt <= lv1.Items.Count - 1; cnt++) {
if (lv1.Items[cnt].SubItems[3].Text == " ")
continue;
string query = "insert into candidate(pid,s_id)values(#pid,#sid)";
MySqlCommand cmd = new MySqlCommand(query, conn);
cmd.Parameters.Add(new MySqlParameter("#pid", lv1.Items[cnt].SubItems[0].Text ));
cmd.Parameters.Add(new MySqlParameter("#sid", lv1.Items[cnt].SubItems[2].Text));
cmd.Transaction = mt;
cmd.ExecuteNonQuery();
}
mt.Commit();
} catch (Exception error) {
MessageBox.Show(error.Message);
mt.Rollback();
}
conn.Close();
This is my dummy student table:
This is my dummy position table:
This is my dummy candidate table:
This is my listview control sample:
Don't rely on an exception from the insert statement: if you don't insert anything, there is no need to perform a rollback.
Instead, check to see if the item already exists and only insert if it does not. If you need to tell the user that it already exists, you can show the message box.
For example:
// This is just an example; not sure what exact conditions you need
var cmdExists = new MySqlCommand("SELECT 1 FROM candidate WHERE pid = #pid");
cmdExists.Parameters.Add(new SqlParameter("#pid", lv1.Items[cnt].SubItems[0].Text));
if (cmdExists.ExecuteScalar() == DBNull.Value)
{
string query = "insert into candidate(pid,s_id)values(#pid,#sid)";
...
} else {
MessageBox.Show("some error message that makes sense to your user");
}
Related
I'm trying to insert all the data from 3 list-boxes to a table in the database i don't know if i'm doing well , this is the code i used
private void Order()
{
using (SqlConnection connection = new SqlConnection(connectionString1))
{
String query = "INSERT INTO Tbl_order (OrderName,Quantity,Price,Serves_way,Date) VALUES (#OrderName,#Quantity, #Price,'"+servers+"','" + time1.ToString(format1)+"' )";
using (SqlCommand command = new SqlCommand(query, connection))
{
connection.Open();
for (int i = 0; i < lst_OrderName.Items.Count; i++)
{
string OrderName = lst_OrderName.GetItemText(lst_OrderName.GetSelected(i));
command.Parameters.AddWithValue("#OrderName", lst_OrderName.GetItemText(lst_OrderName.GetSelected(i)));
command.Parameters.AddWithValue("#Quantity", lst_QTY.GetItemText(lst_QTY.GetSelected(i)));
command.Parameters.AddWithValue("#Price", lst_Price2.GetItemText(lst_Price2.GetSelected(i)));
command.Parameters.Add("#OrderName", SqlDbType.NVarChar);
command.Parameters.Add("#Quantity", SqlDbType.Int);
command.Parameters.Add("#Price", SqlDbType.Money);
command.Parameters.Add("#OrderName", SqlDbType.NVarChar).Value = OrderName;
command.Parameters.Add("#Quantity", SqlDbType.Int).Value = Convert.ToInt32(lst_QTY.GetSelected(i));
command.Parameters.Add("#Price", SqlDbType.Money).Value = Convert.ToDouble(lst_Price2.GetSelected(i));
}
// command.Parameters.AddWithValue("#OrderName", lst_OrderName.GetItemText(lst_OrderName.SelectedItem));
//command.Parameters.AddWithValue("#Quantity", lst_QTY.GetItemText(lst_QTY.SelectedItem));
//command.Parameters.AddWithValue("#Price", lst_Price2.GetItemText(lst_Price2.SelectedItem));
int result = command.ExecuteNonQuery();
// Check Error
if (result < 0)
Console.WriteLine("Error inserting data into Database!");
}
}
}
and i have a problem which is says
An unhandled exception of type 'System.Data.SqlClient.SqlException' occurred in System.Data.dll
Additional information: The variable name '#OrderName' has already been declared. Variable names must be unique within a query batch or stored procedure.
this is the pic of the three list-boxes [![enter image description here][1]][1]
What is wrong in code what did i miss?
I want the data to be inserted in the database for each row like how does it look like in the pic .
You're trying to re-add the same parameters multiple times in a loop before ever executing the query. Even in a single iteration of the loop, you try to add every parameter three times. The error is telling you that you can only add the same parameter once.
Move the entire lifespan of the query to inside the loop. Something like this:
connection.Open();
for (int i = 0; i < lst_OrderName.Items.Count; i++)
{
using (SqlCommand command = new SqlCommand(query, connection))
{
command.Parameters.Add("#OrderName", SqlDbType.NVarChar).Value = OrderName;
command.Parameters.Add("#Quantity", SqlDbType.Int).Value = Convert.ToInt32(lst_QTY.GetSelected(i));
command.Parameters.Add("#Price", SqlDbType.Money).Value = Convert.ToDouble(lst_Price2.GetSelected(i));
command.ExecuteNonQuery();
}
}
This would also be a good time to learn about using transactions with a database. That way you can wrap all of these inserts in a single transaction and commit or rollback as needed.
I want to make a extra control in my C# application if the record exist.
I have got the following code - but it keeps returning a result of -1 even though the record does exist in the SQL Server database.
Can someone help me with this? I have added --> for where it went wrong
private void btnVerwijderen_Click(object sender, RoutedEventArgs e)
{
if (autonrTextBox.Text == "")
{
MessageBox.Show("Waarschuwing u kunt geen auto verwijderen indien er GEEN autonr is ingevuld");
}
else
{
--> SqlConnection con = new SqlConnection(#"Data Source=DESKTOP-RSEBNR7;Initial Catalog=AudiDealer;Integrated Security=True");
--> string check = "SELECT autonr FROM auto WHERE autonr =#autonr";
--> SqlCommand command1 = new SqlCommand(check, con);
--> command1.Parameters.AddWithValue("#autonr", autonrTextBox.Text);
con.Open();
int auto = command1.ExecuteNonQuery();
con.Close();
--> X - 1 MessageBox.Show(auto.ToString());
if (auto > 0)
{
try
{
con.Open();
using (SqlCommand command = new SqlCommand("DELETE FROM auto WHERE autonr =" + autonrTextBox.Text, con))
{
command.ExecuteNonQuery();
}
con.Close();
}
catch (SystemException ex)
{
MessageBox.Show(string.Format("An error occurred: {0}", ex.Message));
}
}
else
{
MessageBox.Show("Het opgegeven autonr komt niet voor in de database. controleer deze.");
}
}
}
The ExecuteNonQuery() method doesn't work like you think it does. The return value for this method is the number of rows changed, not anything from the result set. SELECT queries don't change rows, so -1 is the expected result. 0 rows would imply a WHERE clause that matched no rows in an UPDATE, DELETE, or INSERT. -1 is used to indicate a different situation... either a statement that doesn't change rows or a rollback. Check the remarks section in the documentation for the method.
You want to use the ExecuteScalar() method instead.
int auto = -1;
using (var con = new SqlConnection(#"Data Source=DESKTOP-RSEBNR7;Initial Catalog=AudiDealer;Integrated Security=True"))
using (var cmd = new SqlCommand("SELECT autonr FROM auto WHERE autonr =#autonr", con))
{
cmd.Parameters.Add("#autonr", SqlDbType.Int).Value = int.Parse(autonrTextBox.Text);
con.Open();
auto = (int)cmd.ExecuteScalar();
}
Finally... why check before deleting? This is just wasteful. Just issue the DELETE statement. There's no need to do a SELECT first. Your try/catch and the if() checks already handle situations where the record doesn't exist just fine.
int autonr = 0;
if (!int.TryParse(autonrTextBox.Text, autonr))
{
MessageBox.Show("Waarschuwing u kunt geen auto verwijderen indien er GEEN autonr is ingevuld");
}
else
{
try
{
using (var con = new SqlConnection(#"Data Source=DESKTOP-RSEBNR7;Initial Catalog=AudiDealer;Integrated Security=True"))
using (var cmd = new SqlCommand("DELETE FROM auto WHERE autonr = #autonr;", con))
{
cmd.Parameters.Add("#autonr", SqlDbType.Int).Value = autonr;
con.Open();
int result = cmd.ExecuteNonQuery();
if (result <= 0)
{
MessageBox.Show("Het opgegeven autonr komt niet voor in de database. controleer deze.");
}
}
}
catch (SystemException ex)
{
MessageBox.Show(string.Format("An error occurred: {0}", ex.Message));
}
}
Please use ExecuteScalar, ExecuteNonQuery will not return the result.
ExecuteNonQuery return only the the row that was change/add/remove
if you want to know how many you have use in the query Count and get the rows'number
SELECT Count(*) as CountAutonr FROM auto WHERE autonr =#autonr
and then you will get the from the CountAutonr the number of Rows
There're many things wrong in that piece of code, I really recommend you to encapsulate those database queries inside a business class that will connect to the database, retrieve the data and return as a DAO object... but that won't answer your question.
The issue is in the select command execution, ExecuteNonQuery is meant for executing UPDATE, INSERT and DELETE statements, returning the number of affected rows:
con.Open();
**int auto = command1.ExecuteNonQuery();**
con.Close();
You must use ExecuteReader method to retrieve the SELECT results as explained in the following article:
Retrieving Data Using a DataReader
The problem is in command1.ExecuteNonQuery() which returns the number of modified rows. Your query doesn't modify anything but only reads data from database, so the return value will be always -1.
So use ExecuteScalar instead - it will return your autonr value. Just remember to check it for null and cast it to correct type:
int auto = 0;
object result = command1.ExecuteScalar();
if (result != null)
auto = (int)result;
With the code below, I can insert the selected values of the checkboxes into a single line in the database.In the same line, it is added the date, a note, and an Id number from another table (not unique). In my .aspx page there is a simple treenode-checkboxes structure.
Now, I want to insert each selected value from the checkbox in his own line in the database table.
For example: 3 checkboxes are selected: 3 lines with each own value inserted (plus the same date, note, Id for all of them) in the database.
Please any ideas how to do it?
protected void btn_vac_Click(object sender, EventArgs e)
{
int id = Convert.ToInt32(Session["pa_id"]);
string vn = string.Empty;
if (TreeView1.CheckedNodes.Count > 0)
{
foreach (TreeNode node in TreeView1.CheckedNodes)
{
vn += string.Format("{0}", node.Text);
}
}
try
{
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["RegistrationConnectionString"].ConnectionString);
conn.Open();
if (note_vac.Text.Length != 0)
{
string insert_emer = "insert into P_vaccines (V_name,P_Id,Note,Date) values (#vn,#p_id,#note,#Date) ";
SqlCommand com = new SqlCommand(insert_emer, conn);
com.Parameters.AddWithValue("#vn", string.Format("{0}", vn));
com.Parameters.AddWithValue("#p_id", id);
com.Parameters.AddWithValue("#note", note_vac.Text);
com.Parameters.AddWithValue("#Date", DateTime.Now.ToShortDateString());
com.ExecuteNonQuery();
}
else
{
string insert_emer = "insert into P_vaccines (V_name,P_Id,Date) values (#vn,#p_id,#Date) ";
SqlCommand com = new SqlCommand(insert_emer, conn);
com.Parameters.AddWithValue("#vn", string.Format("{0}", vn));
com.Parameters.AddWithValue("#p_id", id);
com.Parameters.AddWithValue("#Date", DateTime.Now.ToShortDateString());
com.ExecuteNonQuery();
}
Response.Write("<script>alert('Success!')</script>");
conn.Close();
}
catch (Exception ex)
{
Response.Write("Error :" + ex.ToString());
}
}
You code could be simplified a lot. First, you should prepare the command before entering the foreach loop over the checked indices. This means, creating the connection and the command then inside the loop just update the values of the parameters that need to change. Something like this.
protected void btn_vac_Click(object sender, EventArgs e)
{
if (TreeView1.CheckedNodes.Count > 0)
{
try
{
string insert_text = "insert into P_vaccines (V_name,P_Id,Note,[Date]) values (#vn,#p_id,#note,#Date) ";
using(SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["RegistrationConnectionString"].ConnectionString))
using(SqlCommand com = new SqlCommand(insert_text, conn))
{
com.Parameters.Add("#vn", SqlDbType.NVarChar);
com.Parameters.Add("#p_id", SqlDbType.Int).Value = Convert.ToInt32(Session["pa_id"]);
com.Parameters.Add("#note", SqlDbType.NVarChar);
com.Parameters.Add("#Date", SqlDbType.NVarChar).Value = DateTime.Now.ToShortDateString();
conn.Open();
foreach (TreeNode node in TreeView1.CheckedNodes)
{
com.Parameters["#vn"].Value = node.Text;
com.Parameters["#note"].Value = note_vac.Text.Length > 0 ? note_vac.Text : DbNull.Value;
com.ExecuteNonQuery();
}
}
Response.Write("<script>alert('Success!')</script>");
}
catch (Exception ex)
{
Response.Write("Error :" + ex.ToString());
}
}
}
Your original problem was caused by the vn +=... statement that concatenates together all the checked nodes. In this code instead I change that value directly on the Parameter with the value of the current check.
Note also that I have removed the AddWithValue calls that is known to be pretty a bad practice. But this means that you should be precise on the datatype of the values that you pass to your database engine. For example that datetime passed as string is a lot suspicious.
I should also add that having a column named Date is very confusing because there is a DataType with that name and if you want to use that column name it is better to encapsulate it with square brackets to avoid Syntax errors (or rename the column)
So I have this code that is designed to delete a row in mySQL server database judging by what is selected in my list box. Here is the code I have to remove the rows:
private void remove_btn_Click(object sender, EventArgs e)
{
try
{
if (Calls_lsb.SelectedItem == null)
MessageBox.Show("Please select an item for deletion.");
}
else
{
int i = Calls_lsb.SelectedIndex;
if (i > 0)
{
SqlConnection connection = new SqlConnection(//My Connection String);
string sqlStatement1 = "DELETE FROM Records WHERE CallID = #Id";
string sqlStatement2 = "DELETE FROM Calls WHERE CallID = #Id";
connection.Open();
SqlCommand cmd1 = new SqlCommand(sqlStatement1, connection);
cmd1.Parameters.AddWithValue("#Id", Calls_lsb.Items[i]);
cmd1.ExecuteNonQuery();
SqlCommand cmd2 = new SqlCommand(sqlStatement2, connection);
cmd2.Parameters.AddWithValue("#Id", Calls_lsb.Items[i]);
cmd2.ExecuteNonQuery();
connection.Close();
Calls_lsb.Items.Remove(Calls_lsb.Items[i]);
}
else
{
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
I get no exceptions and I have similar code that adds records that works fine. I tried stepping into the code but it all seemed fine. It simply just does not delete the row from the database. It removes the correct item from the list, just not the database.
If anyone could shine some light on this situation that would be great, thanks!
Edit : Ok, I seem to have fixed the problem. I just removed the whole i = selected index stuff and replace the 'Calls_lsb.Items[i]' with '(Calls_lsb.SelectedIndex + 1)'. I don't really understand why I was getting an exception when I tried to add 1 to i as this is basically doing the same thing.
Replace your below line code.
cmd1.Parameters.AddWithValue("#Id", Calls_lsb.Items[i]);
//with
cmd1.Parameters.AddWithValue("#Id", Calls_lsb.Items[i].Value);
and
cmd2.Parameters.AddWithValue("#Id", Calls_lsb.Items[i]);
// with
cmd2.Parameters.AddWithValue("#Id", Calls_lsb.Items[i].Value);
my question is very simple:
i have a SQL Table with a column name 'lastname' with fields lastname1,lastname2,lastname3...
In my c# code, i have a method that inserts in the table a row only if the field of the column lastname is not present in the table. This method in input has lastname, so for my INSERT is a parameter.
How can i compare and conseguently check if the field lastname is already in table?
Thanks
You should always use unique constraints in the table if a field must be unique. On that way you prevent duplicates always, even if the input was directly from SSMS or another application.
Then the easiest would be to handle the sql-exception that is raised according to it's number.
....
try
{
int inserted = cmd.ExecuteNonQuery();
} catch (SqlException ex)
{
if (ex.Number == 2601)
{
// show meaningful error message
MessageBox.Show("Cannot insert duplicate key row in object");
}
else
throw;
}
....
This SQL will insert a new record only if the value isn't already in the table:
INSERT INTO Your_Table ( LastName )
SELECT #NewLastName
WHERE NOT EXISTS( SELECT * FROM Your_Table WHERE LastName = #NewLastName )
There are two option one is from sql side another way is from code behind.
unfortunately you can't change your sql code i agree with #David.
from code behind you have to do something like this.
First you have to select all the data from your table and check that data. something like this.
SqlConnection con = new SqlConnection();
SqlCommand cmd = new SqlCommand();
cmd.Connection = con; //Your connection string"
cmd.CommandText = "Select * from table1"; // your query
cmd.CommandType = CommandType.Text;
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
da.Fill(ds);
DataTable dt = new DataTable();
dt = ds.Tables[0];
int count=0;
for (int i = 0; i > dt.Rows.Count; i++)
{
if (Convert.ToString(dt.Rows[i]["LastName"]) == Lastname)
{
count++;
}
}
if (count > 0)
{
//insert code for data
}
else
{
var script = "alert('"+ Lastname + "already exist.');";
ClientScript.RegisterStartupScript(typeof(Page), "Alert", script, true);
// or you can use here your Update statement
}
May this will help you and you can understand.