Multiple Sql Insert String And RollBack With Catch(Exception) - c#

If I have to insert with two sql table and the place of string is as below:
// Single Record Insert
String AA=”Insert into aa(date)values(#date)”;
//Multiple Record Insert with datagridview1
For(int i=0;i<datagridview1.rows.count-1;i++)
{
String BB= “insert into bb(name,amount)values(#name,#amount)”;
}
If there are two different strings of sql insert as per as above by single and multiple insert on Button click Event than Is it possible to handle it on single sql command if yes than reply how?.
But as per I think it is not possible by single SqlCommand and if it is true than there are very big problem to adjust SqlTransaction Class for Rollback and Commit. with try and catch block of the EventHandller
I am really struggling to insert multiple sql statement as above at one Button1_Click Event. Suggest me proper solution or proper way , technique.

You can explicitly define the transactions in your ADO.NET Code.
private void button1_Click(object sender, EventArgs e)
{
SqlConnection db = new SqlConnection("constring");
SqlCommand com = new SqlCommand();
SqlCommand com2 = new SqlCommand();
SqlTransaction tran;
db.Open();
tran = db.BeginTransaction();
try
{
//Run all your insert statements here here
com.CommandText = "Insert into a(Date) Values(#Date)";
com.Connection = db;
com.Transaction = tran;
com.Parameters.Add("#Date", SqlDbType.DateTime);
com.Parameters["#Date"].Value = DateTime.Now;
com.ExecuteNonQuery();
com2.CommandText = "Insert into bb(name,amount) values(#name, #amount)";
com2.Connection = db;
com2.Transaction = tran;
com2.Parameters.Add("#name", SqlDbType.VarChar, 25);
com2.Parameters.Add("#amount", SqlDbType.Decimal);
for (int i = 0; i < datagrid.Rows.Count; i++)
{
//on each loop replace #name value and #amount value with appropiate
//value from your row collection
com2.Parameters["#name"].Value = datagrid.Rows[i].Cells["Name"].Value;
com2.Parameters["#amount"].Value = datagrid.Rows[i].Cells["Amount"].Value;
com2.ExecuteNonQuery();
}
tran.Commit();
}
catch (SqlException sqlex)
{
tran.Rollback();
}
finally
{
db.Close();
}
}

Related

Adding a comma separated list to SQL Server as individual rows

I am trying to get a comma separated list to convert into multiple rows in my database. For example, I am using Winforms and in my textbox I will put "a,b,c"
I want my table to look like this:
but so far I am only achieving :
Here is some sample code for what I am going for:
private void button2_Click(object sender, EventArgs e)
{
for (int i = 0; i < listBox1.Items.Count; i++)
{
listBox1.SetSelected(i, true);
}
string items = "";
StringBuilder sb = new StringBuilder();
foreach (var currentItem in listBox1.SelectedItems)
{
sb.Append(currentItem + ",");
}
items = sb.ToString();
textBox1.Text = items;
}
SQL
string strsql;
strsql = #"UPDATE [table].[dbo].[Departments]
SET [dep_Department] = #department
WHERE [dep_Username] = #username;
IF ##ROWCOUNT = 0
INSERT INTO [table].[dbo].[Departments] ([dep_Username],[dep_Department])
VALUES (#username, #department);";
SqlConnection conn = new SqlConnection(#"coneectionstring;");
var cmd = new SqlCommand(strsql, conn);
cmd.Parameters.Add("#department", SqlDbType.NVarChar, 40).Value = department;
cmd.Parameters.Add("#username", SqlDbType.NVarChar, 60).Value = username;
conn.Open();
cmd.ExecuteNonQuery();
You just need to split the departmentname variable to extract the single departments and then loop over the extracted departments.
But first, if you need to write one record for each department/user pair, then you need to delete all records for that user and then readd them. All this inside a transaction.
Of course I assume that departmentname contains all the departments to be added for the specific user.
So we have two sql command text, the first one deletes the records, the second one adds the record. The SqlCommand and its first parameter are built immediately and the command is used to remove the record, then we can change the command text and add the parameter for the department name outside the loop, and inside the loop you can just update the #department parameter with the current value.
try
{
string clear_recs = #"DELETE FROM [Departments]
WHERE [dep_Username] = #username";
string strsql = #"INSERT INTO [table].[dbo].[Departments]
([dep_Username],[dep_Department])
VALUES (#username, #department);";
using(SqlConnection conn = new SqlConnection(#"coneectionstring;"));
conn.Open();
using(SqlTransaction tr = conn.BeginTransaction());
using(SqlCommand cmd = new SqlCommand(clear_recs, conn, tr));
cmd.Parameters.Add("#username", SqlDbType.NVarChar, 60).Value = username;
cmd.ExecuteNonQuery();
// Change the commandtext and create the parameter
// but do not set the value for now.
cmd.CommandText = strsql;
cmd.Parameters.Add("#department", SqlDbType.NVarChar, 40);
// Split, then loop and update/insert
// using the same SqlCommand.
string[] deps = department.Split(',');
foreach(string dep in deps)
{
cmd.Paramenters["#department"].Value = dep;
cmd.ExecuteNonQuery();
}
// All the write are effectively done here when we commit the transaction
tr.Commit();
}
catch(Exception ex)
{
// Log the errors. If we reach the exception handler, the
// transaction is automatically rolled back and you can try again.
}

Applying transaction on multiple SQL queries

How can i use transaction in single function for multiple insert and update queries? for example:
private void button1_Click(object sender, EventArgs e)
{
// transaction
SqlConnection objConnection = new SqlConnection(annual_examination_system.Properties.Settings.Default.connString);
SqlTransaction objTransaction = null;
int count = 0;
try
{
objConnection.Open();
objTransaction = objConnection.BeginTransaction();
string q1 = "update query"
SqlCommand objCommand1 = new SqlCommand(q1, objConnection, objTransaction);
objCommand1.ExecuteNonQuery();
objTransaction.Commit();
string q2 = "insert query"
SqlCommand objCommand1 = new SqlCommand(q2, objConnection, objTransaction);
objCommand1.ExecuteNonQuery();
objTransaction.Commit();
}
catch (Exception ex)
{
objTransaction.Rollback();
MessageBox.Show(ex.Message);
MessageBox.Show("Exception, Row :" + count);
MessageBox.Show("Transaction Rollback.");
}
finally
{
// Close the connection.
if (objConnection.State == ConnectionState.Open)
{
objConnection.Close();
}
}
now there are two queries one is for update and one is for insert. so do i have to apply transaction separately on them or one transaction can be applied on both?
You can use same transaction for both queries .
Here is an example :
SqlTransaction tran;
Now using this for both the queries
using(SqlConnection connection=new SqlConnection(connection_string))
{
connection.Open();
tran = connection.BeginTransaction();
cmd = new SqlCommand(query1, connection, tran);
cmd1 = new SqlCommand(query2, connection, tran);
count = cmd.ExecuteNonQuery();
count = count + cmd1.ExecuteNonQuery();
tran.Commit();
}
Update : connection is not closing that's the problem. I have edited the code. Please see the update.

Works perfectly except changes are not saved to the SQL database

Changes are not saved to the SQL database
Why would I want to use '#' in the sql statement instead of the way that I have the statement?
Code:
private void button_Save_Customer_Click(object sender, EventArgs e)
{
sqlString = Properties.Settings.Default.ConnectionString;
SqlConnection sqlConnection = new SqlConnection(sqlString);
try
{
string customer_Ship_ID = customer_Ship_IDTextBox.ToString();
string customer_Ship_Address = customer_Ship_AddressTextBox.Text;
SQL = "UPDATE Customer_Ship SET Customer_Ship_Address = customer_Ship_Address WHERE Customer_Ship_ID = customer_Ship_ID";
SqlCommand sqlCommand = new SqlCommand(SQL, sqlConnection);
sqlCommand.Parameters.AddWithValue("Customer_Ship_ID", customer_Ship_ID);
sqlCommand.Parameters.AddWithValue("Customer_Ship_Address", customer_Ship_Address);
sqlCommand.CommandText = SQL;
sqlConnection.Open();
sqlCommand.ExecuteNonQuery();
sqlConnection.Close();
MessageBox.Show("Record Updated");
}
catch (Exception err)
{
MessageBox.Show(err.Message);
}
Here you can check the MSDN reference for the update command.
Use parameters, Why?
Also check that you need to open and close the connection object, not the command.
In case you want to update the rows with the Customer_ID = "something" you could do like this:
The code (updated after your changes):
private void button_Save_Customer_Click(object sender, EventArgs e)
{
string sqlString = Properties.Settings.Default.ConnectionString;
SqlConnection sqlConnection = new SqlConnection(sqlString);
try
{
int customer_Ship_ID;
if(int.TryParse(customer_Ship_IDTextBox.Text, out customer_Ship_ID))
{
string customer_Ship_Address = customer_Ship_AddressTextBox.Text;
// Customer_Ship: Database's table
// Customer_Ship_Address, Customer_Ship_ID: fields of your table in database
// #Customer_Ship_Address, #Customer_Ship_ID: parameters of the sqlcommand
// customer_Ship_ID, customer_Ship_Address: values of the parameters
string SQL = "UPDATE Customer_Ship SET Customer_Ship_Address = #Customer_Ship_Address WHERE Customer_Ship_ID = #Customer_Ship_ID";
SqlCommand sqlCommand = new SqlCommand(SQL, sqlConnection);
sqlCommand.Parameters.AddWithValue("Customer_Ship_ID", customer_Ship_ID);
sqlCommand.Parameters.AddWithValue("Customer_Ship_Address", customer_Ship_Address);
sqlCommand.CommandText = SQL;
sqlConnection.Open();
sqlCommand.ExecuteNonQuery();
sqlConnection.Close();
MessageBox.Show("Record Updated");
}
else
{
// The id of the textbox is not an integer...
}
}
catch (Exception err)
{
MessageBox.Show(err.Message);
}
}
Seems like your syntax isn't correct. Here's the syntax for the Update:
UPDATE table_name
SET column1=value1,column2=value2,...
WHERE some_column=some_value;
So, Update, what to set, and WHERE to set (which you seem to be missing).
For more, have a look here.
Check your update query
Change it like
string SQL = string.format("UPDATE Customer_Ship SET Customer_Ship_Address='{0}'",putUrVaue);

Sending several SQL commands in a single transaction

I have a huge list of INSERT INTO ... strings. Currently I run them with:
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
foreach (var commandString in sqlCommandList)
{
SqlCommand command = new SqlCommand(commandString, connection);
command.ExecuteNonQuery();
}
}
I see that each ExecuteNonQuery() also executes commit.
Is there a way to insert all rows in a single transaction (commit in the end)?
The reason I want a single transaction is to make my "inserts" process faster. Will a single transaction also make it quicker?
Its recommended to use SQL transaction in case you are executing Multiple queries in one thread , you can have it like this :
SqlTransaction trans;
try
{
SqlConnection connection = new SqlConnection(connectionString);
connection.Open();
trans = connection.BeginTransaction();
foreach (var commandString in sqlCommandList)
{
SqlCommand command = new SqlCommand(commandString, connection,trans);
command.ExecuteNonQuery();
}
trans.Commit();
}
catch (Exception ex) //error occurred
{
trans.Rollback();
//Handel error
}
You might probably gain some performance by using just one single transaction and command, as follows:
using (SqlConnection connection = new SqlConnection(connectionString))
{
try
{
connection.Open();
using (SqlTransaction trans = connection.BeginTransaction())
{
using (SqlCommand command = new SqlCommand("", connection,trans))
{
command.CommandType = System.Data.CommandType.Text;
foreach (var commandString in sqlCommandList)
{
command.CommandText = commandString;
command.ExecuteNonQuery();
}
}
trans.Commit();
}
}
catch (Exception ex) //error occurred
{
//Handel error
}
}
A little late, but if you are inserting all of the values into the same table, code the SQL insert as "insert into tablex (f1, f2, f3,...) values (#F1,#F2,#F3...)". Create the command and add the parameters #F1..., and then set the Prepare flag on the command. Now as you loop through your list of values to insert, you can set them into the appropriate parameters and then do the ExecuteNonQuery. SQL will pre-parse the command string once, and then use the new parameters each time. This is a bit faster.
Finally, you can execute multiple SQL statements in a single command by appending ';' to each statement, if you must execute the entire string. You can bunch a number of these commands together and make one request to SQL server to execute them.
You can just concatenate the sql and let the server handle it:
using (SqlConnection connection = new SqlConnection(connectionString))
{
string lsSql = string.Empty;
foreach (var commandString in sqlCommandList)
{
lsSql = lsSql + commandString + " ; " + Environment.NewLine;
}
connection.Open();
SqlCommand command = new SqlCommand(lsSql, connection);
command.ExecuteNonQuery();
}
Here is what I use on my daily work, before it a use a foreach for any non-query that I need to run on database. You can see that I'm using the OracleCommand, but if you need you can change to SQL statement
public static void ExecuteDatabaseNonQuery(string command)
{
OracleCommand cmd = new OracleCommand();
cmd.Connection = conn;
OracleTransaction transaction;
transaction = conn.BeginTransaction(IsolationLevel.ReadCommitted);
cmd.Transaction = transaction;
try
{
cmd.CommandText = command;
var update = cmd.ExecuteNonQuery();
transaction.Commit();
Console.WriteLine("{0} rows updated", update);
}
catch (Exception e)
{
transaction.Rollback();
throw new Exception("Error: " + e);
}
}
Note: If theres any uncommited changes on database this method will wait indefinitely
You can use Parallel for each
using (SqlConnection connection = new SqlConnection(connectionString))
{
List<string> sqlCommandList = new List<string>();
connection.Open();
Parallel.ForEach(sqlCommandList, commandString =>
{
SqlCommand command = new SqlCommand(commandString, connection);
command.ExecuteNonQuery();
});
}

Insert textbox values into database table

What is the easiest and most SQL-like way to insert textbox values into a SQL Server table? I found several ways, and all of them are too complicated for this simple thing I want to do.
If LINQ is too foreign for you, you can still do things the old-fashioned way:
string statement = "INSERT INTO mytable(mycolumn) VALUES (#text)";
SqlCommand command = new SqlCommand(statement);
command.Parameters.AddWithValue("#text", myTextBox.Text);
try{
SqlConnection connection = new SqlConnection(myConnectionString);
connection.Open();
command.Connection = connection;
command.ExecuteNonQuery();
} catch {
//do exception handling stuff
}
Edit: Here's another version that uses using to ensure that messes are cleaned up:
string statement = "INSERT INTO mytable(mycolumn) VALUES (#text)";
using(SqlCommand command = new SqlCommand(statement))
using(SqlConnection connection = new SqlConnection(myConnectionString)) {
try{
command.Parameters.AddWithValue("#text", myTextBox.Text);
connection.Open();
command.Connection = connection;
command.ExecuteNonQuery();
} catch {
//do exception handling stuff
}
}
If you want to do something quickly, use LINQ to SQL. It will take care of your Data Access Layer & Business objects.
Just go to LINQ to SQL Classes on Visual Studio & map your SQL server and add any tables you want to it.
Then you can use the objects it creates in your code behind to update values from textboxes.
http://weblogs.asp.net/scottgu/archive/2007/05/19/using-linq-to-sql-part-1.aspx
public string ConnectionString
{
get
{
//Reading connection string from web.config
return ConfigurationManager.ConnectionStrings["ConnectionName"].ConnectionString;
}
}
public bool InsertEmployee()
{
bool isSaved = false;
int numberOfRowsAffected = 0;
string query = #"INSERT INTO Employee(EmployeeName, EmailAddress)
VALUES (#EmployeeName, #EmailAddress);
SELECT ##IDENTITY AS RowEffected";
SqlCommand cmd = new SqlCommand();
cmd.CommandText = query;
cmd.CommandType = System.Data.CommandType.Text;
cmd.Parameters.Add(new SqlParameter("#EmployeeName", txtEmployeeName.Text));
cmd.Parameters.Add(new SqlParameter("#EmailAddress", txtEmailAddress.Text));
try
{
using (SqlConnection cn = new SqlConnection(ConnectionString))
{
cmd.Connection = cn;
cn.Open();
object result = cmd.ExecuteScalar();
isSaved = Convert.ToInt32(result) > 0 ? true : false;
}
}
catch (Exception ex)
{
isSaved = false;
}
return isSaved;
}
But, in multiple layer or multi-tier application you do need to create DTO(Data Transfer Object) to pass the data from layer to layer(or tier to tier)
Here's a simple way to do it. It looks complex because of the number of rows: Inserting Data in SQL Database

Categories