I found a few links regarding rolling back a SQL Server query but have had problems implementing it. Since the information I am inserting and updating needs to always be correct I need to make sure this is working beforehand. Now, I already have a try/catch block, and I know the rollback goes into the catch block. For example, this is my code:
using (SqlConnection conn5 = new SqlConnection(connString))
{
try
{
string query = "INSERT QUERY";
SqlCommand cmd = new SqlCommand(query, conn5);
// PARAMETERS
conn5.open();
cmd.ExecuteNonQuery();
}
catch
{
cmd.Rollback();
}
}
I tried cmd.RollBack() but it just blew in my face.
You open a transaction scope. It will automatically perform a rollback unless the Complete() method is called.
using (var tScope = new TransactionScope())
using (SqlConnection conn5 = new SqlConnection(connString))
{
string query = "INSERT QUERY";
SqlCommand cmd = new SqlCommand(query, conn5);
PARAMETERS
conn5.open();
cmd.ExecuteNonQuery();
// If an exception is thrown, the call to Complete() will never be reached and the
// changes will be rolled back.
tScope.Complete();
}
Related
Because SqlCommand implements IDisposable, I would normally approach an ADO query as follows.
using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand(query, connection))
{
// Execute command, etc. here
}
However, what if I need to execute multiple commands during a single connection? Do I really need a new using block for each command?
The examples I found from Microsoft don't use a using block for SqlCommands (or even call Dispose()). What are best practices regarding disposing SqlCommand?
Sure, best practice is to dispose them.
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
using (SqlCommand command1 = new SqlCommand(query1, connection))
{
// Execute command, etc. here
}
using (SqlCommand command2 = new SqlCommand(query2, connection))
{
// Execute command, etc. here
}
using (SqlCommand command3 = new SqlCommand(query3, connection))
{
// Execute command, etc. here
}
}
MSDN probably doesn't show it because it's not really needed in case of SqlCommand. But in my opinion it's bad from microsoft to not use this pattern on every object that implements IDdisosable because people aren't getting used to it.
The using statement ensures that Dispose is called even if an exception occurs while you are calling methods on the object. You can achieve the same result by putting the object inside a try block and then calling Dispose in a finally block.
In this case you use using for each command block:
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (SqlCommand cmd1= new SqlCommand(query1, connection))
{
}
using (SqlCommand cmd2= new SqlCommand(query2, connection))
{
}
}
No you do not. There are 2 ways that your multiple commands could be bundled within one connection and command.
The first would be to just reuse the existing CMD object, but changing the CommandText and other CMD.properties as needed.
using (SqlConnection con = new SqlConnection(connectionString)) {
con.Open();
using (SqlCommand cmd = new SqlCommand(query1, con)) {
// cmd.CommandType = CommandType.xxxxx
// add any parameters
// Execute()
cmd.CommandText = query2;
// reset CommandType if needed
// adjust parameters if needed
// Execute()
cmd.CommandText = query 3;
// reset CommandType if needed
// adjust parameters if needed
// Execute()
}
con.Close();
}
The second method would be to create a Stored Procedure on the database server and call that in the one CMD object
-- Database
CREATE PROCEDURE schema.sproc_CommandBatch (
-- any variables here
) AS
BEGIN
-- query 1
-- query 2
-- query 3
END
GO
// C#
using (SqlConnection con = new SqlConnection(connectionString)) {
con.Open();
using (SqlCommand cmd = new SqlCommand("schema.sproc_CommandBatch", con)) {
// cmd.CommandType = CommandType.StoredProcedure
// add any parameters
// Execute()
}
con.Close();
}
Best practice is that if it implements IDisposable then Dispose() it. In fact the examples here do all call Dispose. With a wrinkle:
The first example, where it opens a SqlDataReader, calls .Close() on the command in the finally clause. In fact, .Close is just a wrapper around .Dispose() (and no longer appears in the documentation). Jonathan Wood in his comment pointed out that the Close is on the reader. This is wrong.
For multiple calls on the same connection you can:
Re-use the one command (declared in one using). I don't like this
myself, but that's just me: I find it...ugly.
Use multiple commands in multiple usings. That's what I'd do.
'Best Practice' is a bit amorphous. There's never unanimous agreement that what person A touts as Best Practice is better than what person B is recommending, let alone C, D or E. Use your own judgement.
I've been using
connection.Close();
But this is my first project in .NET and I'm not sure if I'm closing it correctly.
I don't want my website to instantly die after putting it out on real hosting.
Usually I do it this way:
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ToString());
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
// <some code>
conn.Open();
/ <some code>
conn.Close();
You should place the connection in a using statement;
using(var connection = new SqlConnection)
{
connection.Open();
...other code using it here.
}
The using statement ensures that the SqlConnection is disposed when you are done with it. In your scenario (depending on where you put the close method), if an exception is closed, it will never reach the Close() method and the connection will stay open.
Even better is that since you are building a website. There should be a method on the Request object (which should be available) called RegisterForDispose. This will automatically Dispose of the connection (which closes it) when the request ends. You can use it like this:
var connection = new SqlConnection();
Request.RegisterForDispose(connection);
Both accomplish the same thing in the end, but the second allows for more flexibility.
Do what Kevin said and put your .Open() call inside the using block:
using(var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ToString()))
{
var cmd = new SqlCommand("my sql command here", conn);
conn.Open();
cmd.(whatever method you are using)
}
I'm trying to save a note into the database by user input but my code isn't saving it to the Database.
I'm planning on checking the user input aswell with functions.
SqlConnection con = database.GetConnection();
SqlCommand command = new SqlCommand("INSERT INTO notities (notities_gebruiker, notities_datum, notities_doeldatum, notities_bericht) values(#notities_gebruiker, #notities_datum, #notities_doeldatum, #notities_bericht)", con);
command.Parameters.AddWithValue("#notities_gebruiker", this.gebruikerid.ToString());
command.Parameters.AddWithValue("#notities_datum", DateTime.Now);
command.Parameters.AddWithValue("#notities_doeldatum", DateTime.ParseExact(this.targetDate.Text, "dd/MM/yyyy", null));
command.Parameters.AddWithValue("#notities_bericht", this.Note.Text);
con.Open();
command.ExecuteNonQuery();
con.Close();
initialiseListBox();
What's happening is that whenever I close my application the database loses it's values saved and goes back to original state. I can add items manually though..
EDIT: It rolls back the rows I have added in via application but I am able to pull the data from the database I saved if I keep it running.
You're forgetting to commit the data you've just inserted. Use the SqlTransaction class to begin a transaction:
SqlTransaction myTransaction = con.BeginTransaction();
command.ExecuteNonQuery();
myTransaction.Commit();
It would be a good idea to make use of the Using statement to make sure your connection, command and transaction are disposed of once the code block has been complete, rather than manually calling Close() methods:
Using (SqlConnection con = database.GetConnection())
{
con.Open();
Using (SqlCommand command = new SqlCommand("sqlhere"))
{
Using (SqlTransaction myTransaction = con.BeginTransaction())
{
//your code here
}
}
}
SqlTransaction class:
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqltransaction(v=vs.110).aspx
Neat article on using statements:
http://www.codeproject.com/Articles/6564/Understanding-the-using-statement-in-C
Look for a copy of your database containing the data in your bin/debug folder.
Best way to avoid this is to use a full path in your connection string and avoid |DataDirectory| while debugging
i want to delete data in my database and using this code but its now working
private static void DeletePreviousRecord()
{
string connectionString = "Data Source=ABDULLAH\\ABDULLAHZAFAR;Initial Catalog=FoodHunt;Integrated Security=True";
using (SqlConnection con = new SqlConnection(connectionString))
{
using (SqlCommand cmd = new SqlCommand("Delete From RestaurantsMenu", con))
{
try
{
cmd.CommandType = CommandType.StoredProcedure;
con.Open();
var result = cmd.ExecuteNonQuery();
con.Close();
}
catch (Exception ex)
{ }
}
}
}
i tried this but this is not working, how can i do that, any suggestion?
Setting the CommandType to StoredProcedure when you clearly use a sql text directly cannot do any good at your code.
Remove that line because the default is CommandType.Text (and this is correct for your command)
But as stated in the comment above.
If you catch the exception, at least write in some log or display at
video what the error message is
If you don't add a WHERE clause at your sql statement, you delete
everything in the table (Probably you are lucky that this code has
not worked)
Looking at your comment below, if you want to delete every record (and reset the Identity column if any) a faster approach is
using (SqlCommand cmd = new SqlCommand("TRUNCATE TABLE RestaurantsMenu", con))
For a quick reading about the difference between TRUNCATE and DELETE look at this article
I don't know much about exporting data using OLEDB, I figured the following:
using (OleDbConnection conn = new OleDbConnection(connString))
{
try
{
conn.Open();
foreach (T t in rows)
{
using( OleDbCommand oleDbCommand = new OleDbCommand(insertString, conn))
{
OleDbParameter param = new OleDbParameter(.., ..);
oleDbCommand.Parameters.Add(param);
//add more parameters
oleDbCommand.ExecuteNonQuery();
}
}
}
catch (Exception e)
{
//handle
}
}
At first, I didn't use the using statement for the OleDbCommand (i.e., I didn't dispose of the OleDbCommand). But in that case, a record locking file remained on the database even though I was finished exporting. WITH the (inner) Using statement however, exporting seems slower. Why? And how to get both the fast exporting and the removal of the record locking at the end of exporting?
Since you do not close the Connection, the ldb file remains present as you're still connected to the DB.
So, you should put a using statement around the connection-declaration (or close the connection in the finally block of your try statement [which is exactly what the using statement does nb).
using( var conn = new OleDbConnection (connectionstring) )
{
conn.Open();
using( cmd = conn.CreateCommand() )
{
cmd.Parameters.Add (..);
...
for( ... )
{
cmd.Parameters.Clear();
cmd.CommandText = "";
cmd.Parameters["#p_param"].Value = ...
cmd.ExecuteNonQuery();
}
}
}
With the using clause in the for-loop, you're disposing the OleDbCommand for every record that you're going to insert. However, you can re-use the OleDbCommand instance for every insert. (See code above).
Next to that, you should start a transaction explicitly. Since, when you do not do that, an implicit transaction will be created for each insert statement.
Also, by performing all the inserts inside one transaction, you'll be able to rollback all the changes (inserts) that you've done when you encounter an error.
(For instance, if inserting row nr 159 fails, you can rollback all the 158 inserts that you've done before).