Rollback changes when code not executed properly - c#

I am new to SQL, In my project I am trying to fill the DataSet from the DataBase table and then inserting new rows in DataSet. After doing this, again I am filling the Database table with the DataSet data. Before filling I am clearing or deleting the Database table data. Well I achieved this by using the below code:
Database Table --> myTable
DataSet --> ds
OnButtonClick
string strQuery = "delete from [dbo].[myTable]"
SqlConnection conn = new SqlConnection(strConn);
SqlCommand cmd = new SqlCommand(strQuery, conn);
SqlCommand command;
SqlDataAdapter da = new SqlDataAdapter(cmd);
using (cmd)
{
using (conn)
{
conn.Open();
cmd.ExecuteNonQuery(); //deleting database table data
foreach (DataRow dr in ds.Tables[0].Rows) //Inserting new data into the Database table
{
command = new SqlCommand(InsertQuery, conn);
command.ExecuteNonQuery();
}
conn.Close();
}
}
The above code is working fine but when there is any exception in command sqlCommand then it is deleting the database table completely and not filling the DataSet. Any suggestions to modify this code? please help.
UPDATE:
string strQuery = "delete from [dbo].[myTable]";
using (SqlCommand cmd = new SqlCommand(strQuery, conn))
{
using (SqlCommand cmdReset = new SqlCommand("DBCC CHECKIDENT('myTable', RESEED, 0)", conn))
{
SqlDataAdapter da = new SqlDataAdapter(cmd);
conn.Open();
SqlTransaction sqlTransaction = conn.BeginTransaction();
cmd.Transaction = sqlTransaction;
try
{
cmd.ExecuteNonQuery(); //deleting database table data
cmdReset.ExecuteNonQuery(); //Resetting Identity of first column
foreach (DataRow dr in ds.Tables[0].Rows) //Inserting new data into the Database table
{
command = new SqlCommand(query.createDoctorRow(InsertQuery, conn);
command.ExecuteNonQuery();
}
sqlTransaction.Commit();
conn.Close();
}
catch (Exception e)
{
sqlTransaction.Rollback();
/*ERROR*/ throw;
}
}
}
ERROR --> "ExecuteNonQuery requires the command to have a transaction when the connection assigned to the command is in a pending local transaction. The Transaction property of the command has not been initialized."

Use a transaction to run the sql
string strQuery = "delete from [dbo].[myTable]";
using (SqlConnection conn = new SqlConnection(strConn))
{
using (cmd = new SqlCommand(strQuery, conn))
{
SqlDataAdapter da = new SqlDataAdapter(cmd);
conn.Open();
SqlTransaction sqlTransaction = conn.BeginTransaction();
cmd.Transaction = sqlTransaction;
try
{
cmd.ExecuteNonQuery(); //deleting database table data
foreach (DataRow dr in ds.Tables[0].Rows) //Inserting new data into the Database table
{
command = new SqlCommand(InsertQuery, conn);
command.ExecuteNonQuery();
}
sqlTransaction.Commit();
conn.Close();
}
catch(Exception e)
{
sqlTransaction.Rollback();
throw;
}
}
}
Transactions form an all or nothing scenario. Either everything in the transaction works and is committed to the database, or the whole lot is cancelled as if nothing happened.

This example has a nice way of wrapping sql commands in a transaction scope. Basically if any exception is thrown during any of the row insert the delete query will fail as well.
In a nut shell you wrap everything inside a
using (TransactionScope scope = new TransactionScope())
{
using (SqlConnection connection1 = new SqlConnection(connectString1))
{
//enter your code here
}
}
Also you don't have to do an insert row by row you can use the SqlBulkCopy to do it more efficiently.
using (SqlConnection connection =new SqlConnection(connectionString))
{
connection.Open();
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection))
{
bulkCopy.DestinationTableName = table.TableName;
bulkCopy.WriteToServer(table);
}
}

Related

Retrieve table names

I'm trying to retrieve the names of the table from the local database I'm using.
This the code I've tried but it never goes through the foreach loop:
public void GetColumnNames()
{
SqlConnection con;
SqlDataAdapter adapter = new SqlDataAdapter();
DataSet ds = new DataSet();
con = new SqlConnection(Properties.Settings.Default.AlhusainSoundDBConnectionString);
List<string> colns = new List<string>();
try
{
con.Open();
}
catch (SqlException ex)
{
MessageBox.Show(ex.Message);
}
foreach (DataTable dt in ds.Tables)
{
colns.Add(dt.TableName);
Console.WriteLine(dt.TableName);
}
}
So could anyone please suggest me how to do that correctly
Regards
To get table names you need to use INFORMATION_SCHEMA
USE <your_database_name>
GO
SELECT * FROM INFORMATION_SCHEMA.TABLES
You haven't done anything except open a connection to the database. Your dataset has not been populated with any data. My approach would be to use a SqlCommand object to execute the following SQL Statement and populate a SqlDataReader
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
So, the C# code might look something like this:
string sql = "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES";
using (SqlConnection con = new SqlConnection(Properties.Settings.Default.AlhusainSoundDBConnectionString))
using (SqlCommand cmd = new SqlCommand(sql, con))
{
con.Open();
using (SqlDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
{
// do something with each table
string tableName= dr["TABLE_NAME"].ToString();
// OR
// string tableName = dr[0].ToString();
// OR
// string tableName = dr.GetString(0);
}
}
}

Oracle database table in gridview

I want to get the result from a query in my oracle database and put it in a gridview. Now my problem is, I have no idea how to output it in the gridview. I am using the gridview from the toolbox and my oracle connection is working. I also have the right SELECT query and I can output that in a listbox. I just have no idea how to do this in a gridview. I looked for it and I came across this: How to populate gridview with mysql? Although this doesn't help me.
How can I output it in a gridview so that it looks exactly the same as a normal table in the oracle database?
What should I use and how?
This is my code:
public void read()
{
try
{
var conn = new OracleConnection("")
conn.Open();
OracleCommand cmd = new OracleCommand("select * from t1", conn);
OracleDataReader reader = cmd.ExecuteReader();
DataTable dataTable = new DataTable();
while (reader.Read())
{
var column1 = reader["vermogen"];
column = (column1.ToString());
listBox1.Items.Add(column);
}
conn.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
To bind a DataTable to a DataGridView your code need simply to be changed to
public void read()
{
try
{
using(OracleConnection conn = new OracleConnection("....."))
using(OracleCommand cmd = new OracleCommand("select * from t1", conn))
{
conn.Open();
using(OracleDataReader reader = cmd.ExecuteReader())
{
DataTable dataTable = new DataTable();
dataTable.Load(reader);
dataGridView1.DataSource = dataTable;
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
The OracleDataReader could be passed to the Load method of the DataTable and then the table is ready to be bound to the DataGridView DataSource property. I have also added some using statement to ensure proper disposing of the disposable objects employed. (In particular the OracleConnection is very expensive to not close in case of exceptions)
You can use DataSet too:
public void read()
{
try
{
OracleConnection conn = new OracleConnection("");
OracleCommand cmd = new OracleCommand("select * from t1", conn);
conn.Open();
cmd.CommandType = CommandType.Text;
DataSet ds = new DataSet();
OracleDataAdapter da = new OracleDataAdapter();
da.SelectCommand = cmd;
da.Fill(ds);
dataGridView1.DataSource = ds.Tables[0];
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
First establish connection in case, you didnt establish globally by using connection string. Then use oleDbcommand for the oracle sql command you want to execute. In my case, it is 'select * from table_name' which would show all data from table to datagrid. I wrote this code in a button to display data on data grid.
{
OleDbConnection conn = new OleDbConnection("");
OleDbCommand cmd = new OleDbCommand("select * from table_name", conn);
{
conn.Open();
OleDbDataReader reader = cmd.ExecuteReader();
{
DataTable dataTable = new DataTable();
dataTable.Load(reader);
dataGridView1.DataSource = dataTable;
}
conn.Close();
}
}

Query Multiple Databases SQL Server

I'm having a problem running a query across multiple databases on an Azure SQL Server. This is the function I have made to return a DataTable from the query once it has been executed. The function takes the database name as a string and inserts it into the conenction string, along with the query to be executed.
The function works fine when I run it once, returning the DataTable populated with returned rows as intended, but when I call the function using a 'foreach' statement (Iterating through a list of database names) I get a timeout error or a login failed error.
Any help on this would be appreciated.
public static DataTable runQuery(String db, String query)
{
using (SqlConnection con = new SqlConnection("Data Source=server.database.windows.net;Initial Catalog=" + db + ";User ID=user#server;Password=password"))
{
con.Open();
using (DataTable dt = new DataTable())
{
try
{
SqlCommand cmd = new SqlCommand(query, con);
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dt);
cmd.Dispose();
da.Dispose();
}
catch (SqlException ex)
{
MessageBox.Show(ex.Message);
}
return dt;
}
}
}
Add cmd.CommandTimeout = 0
try
{
SqlCommand cmd = new SqlCommand(query, con);
cmd.CommandTimeout = 0;
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dtt);
cmd.Dispose();
da.Dispose();
}
I think you should try adding System.Threading.Thread.Sleep inside the foreach block.

How to insert results from one database to another in c# application

How can you connect the result of a query from one database and insert it into another in a c# application?
This is what I have so far but it doesnt work.
// select from first database
string sCMD_All = "SELECT * FROM table";
SqlDataAdapter da = new SqlDataAdapter();
DataSet ds = new DataSet();
using (SqlConnection myConn = new SqlConnection(ConnectionString))
{
using (SqlCommand myCommand = new SqlCommand(sCMD_All, myConn))
{
myConn.Open();
SqlDataReader reader = myCommand.ExecuteReader();
da.Fill(ds);
myConn.Close();
}
}
DataTable sqTable = ds.Tables[0];
//insert into 2nd database
DataTable newTable = new DataTable();
newTable = sqTable;
using (SqlConnection myConn = new SqlConnection(ConnectionString_M))
{
string sCMD_I = "INSERT INTO tableNew #newTable";
using (SqlCommand myCommand = new SqlCommand(sCMD_I, myConn))
{
myConn.Open();
SqlDataReader reader = myCommand.ExecuteReader();
myConn.Close();
}
}
var commandText =
#"insert into [server].[database2].[schema].[table] (col1, col2, ...)
select col1, col2, ... from [server].[database1].[schema].[table]";
using (var connection = new SqlConnection(connectionString))
{
using (var command = new SqlCommand(commandText, connection))
{
connection.Open();
command.ExecuteNonQuery();
}
}
NOTE: If databases are located on different servers, you should link servers:
exec sp_addlinkedserver #server = 'server2'

Adding data to data row of database in c#

I am facing a little problem in my code to add data to sql database attached with my program in ASP.net/C#. Here's code:
string ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["sqlconnection"].ConnectionString;
SqlConnection cnn = new SqlConnection(ConnectionString);
cnn.Open();
SqlCommand cmd = new SqlCommand();
cmd.CommandText = "select Id from TableName";
cmd.Connection = cnn;
SqlDataAdapter da = new SqlDataAdapter();
da.SelectCommand = cmd;
DataSet ds = new DataSet();
da.Fill(ds, " TableName ");
SqlCommandBuilder cb = new SqlCommandBuilder(da);
DataRow drow = ds.Tables["TableName"].NewRow();
drow["Id"] = TextBox1.Text;
ds.Tables["TableName "].Rows.Add(drow);
da.Update(ds, " TableName ");
string script = #"<script language=""javascript"">
alert('Information have been Saved Successfully.......!!!!!.');
</script>;";
Page.ClientScript.RegisterStartupScript(this.GetType(), "myJScript1", script);
Even when I entered any integer value to the text box, it shows an error message that object is not set to an instance on code:
DataRow drow = ds.Tables["TableName"].NewRow();
Please guide.
Thanks.
This seems like a very bad way of inserting data. Have you looked at the Entity Framework or Linq2Sql? Alternatively you could just use a standard SqlCommand and set the CommandText yourself.
Any of these would provide a cleaner solution.
Eg: With ADO.NET (Connecting to SQLite):
var conn = new SQLiteConnection(string.Format(Constants.SQLiteConnectionString, "db.db3"));
conn.Open();
using (SQLiteTransaction trans = conn.BeginTransaction()) {
using (var cmd = conn.CreateCommand()) {
cmd.CommandText = "INSERT INTO TableName (Id) VALUES (#Id)";
cmd.Parameters.AddWithValue("#Id", someTextVariable);
cmd.ExecuteNonQuery();
}
}

Categories

Resources