Check if SqlTransaction is rolled back - c#

In my application I create a sql transaction
SqlTransaction importTrans = GPConnection.BeginTransaction();
And then I call several stored procedures in that transaction. If one of the stored procedures fails, it logs the error and it rolls back.
catch (Exception ex)
{
cError.LogException(ex);
importTrans.Rollback();
}
My question is: Is there a way for me to know, before I call the next stored procedure, that the transaction has been rolled back? Here's my code with a commented version of something I want to do.
using (SqlCommand oCmd = new SqlCommand("taHR2APP13", importTrans.Connection, importTrans))
{
oCmd.CommandType = CommandType.StoredProcedure;
oCmd.Transaction = importTrans;
//if (!importTrans.IsRolledBack)
oCmd.ExecuteNonQuery();
}

Related

Why does the same MySql query behaves differently in code and workbench?

Here is a simple mysql query run from my application:
try
{
using (var connection = new MySqlConnection(connectionString))
{
var storedProcedure = "ReserveConstructB";
using (var command = new MySqlCommand(storedProcedure, connection))
{
command.CommandType = CommandType.StoredProcedure;
connection.Open();
command.ExecuteNonQuery();
}
}
}
and here is simple stored procedure:
BEGIN
start transaction;
select *from Kimmel_constructs for update;
END
As you can see I do not COMMIT at the end of the procedure, but regardless, when I run this procedure next time it gets executed even though "Kimmel_constructs" is not released and I should get lock_wait_timeout exception. If I call the same procedure in MySql Workbench from different connections, I get the exception which would be the desired behavior. What could be the reason for such a behavior?
Because your application probably makes busy mysql. So you need to close connection when your progress done like connection.Close() and I suggest to use:
if (con.State==ConnectionState.Open)
{
con.Close();
}
con.Open();

I have 5 methods which use stored procedures,i want SqlTransaction for all 5 methods at once

i have this error message:"
When the command assigned to the command is in the pending local
process, ExecuteNonQuery requires the command to have a process. The
Command property of the command has not been initialized." I get id
from first method to use for other 4 methods.
this is my code;
SqlTransaction myTransaction;
try
{
myconnection.Open();
KisiBilgiKaydet();
EgitimBilgiKaydet();
SinavBilgiKaydet();
ProgramBilgiKaydet();
BelgeKaydet();
myTransaction.Commit();
myconnection.Close();
}
catch (Exception ex)
{
myTransaction.Rollback();
myconnection.Close();
}
You should put in the transaction to each SqlCommand in all methods you needed in:
SqlTransaction transaction;
try
{
myconnection.Open();
transaction = myconnection.BeginTransaction();
KisiBilgiKaydet(transaction);
EgitimBilgiKaydet(transaction);
SinavBilgiKaydet(transaction);
ProgramBilgiKaydet(transaction);
BelgeKaydet(transaction);
transaction.Commit();
myconnection.Close();
}
catch (Exception ex)
{
transaction.Rollback();
myconnection.Close();
}
And be sure to use the transaction in the methods like:
private void sqlMethod(SqlTransaction transaction)
{
var cmd = new SqlCommand(sqlQuery, connection, sqlTransaction);
}
If you want to use SqlTransaction, then that's fine - but you need to pass the transaction in to each method (or otherwise make it available to them), and the code in each method needs to explicitly use that transaction and connection. But in principle: fine, have fun!
There is also ambient transactions aka TransactionScope - this is simpler to use, but a: doesn't work on .NET Core, and b: has a nasty habit of escalating to an MSDTC transaction (which is: bad). So personally: I'd just pass the transaction in.

ODBC transaction does not roll back

I have referred this to perform rollback operation in my wpf c# application. The code that I tried is as follows:
using (OdbcConnection connection = new OdbcConnection("connectionString"))
{
OdbcCommand command = new OdbcCommand();
OdbcTransaction transaction = null;
command.Connection = connection;
try
{
connection.Open();
transaction = connection.BeginTransaction();
command.Connection = connection;
command.Transaction = transaction;
command.CommandText = "INSERT INTO TableA (A, B, C) VALUES (10,10,10)";
command.ExecuteNonQuery();
command.CommandText = "NSERT INTO TableB (D,E,F) VALUES (20,20,20)";
command.ExecuteNonQuery();
transaction.Commit();
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
try
{
transaction.Rollback();
}
catch
{
}
}
Intentionally the second query has been made wrong. My intention is that when I enter the catch block on calling transaction.Rollback() the values added due to executing of the first query in TableA are not reflected since Rollback was called. However this is not the case the values are not rolledback and are present in TableA. I have searched various resources online with no luck. I cannot use SqlConnection instead of OdbcConnection my application does not support that. Is there any work around this or alternative method that can achieve what I have in mind. Please help me out.
You have basically MSDN example. I had once another problem with ODBC and the issue was with ODBC vendor drivers. I would strongly recommend check that possibility.

C# - Oracle Transaction Exception - Lot of users at same time - "Execute requires the Command object to have a Transaction..."

I've developed a web application. Some methods use Transactions. Everything works fine,
except when several users start using the webapplication at the same
time. I often get the following message:
"Execute requires the Command object to have a Transaction object when the Connection object assigned to the Command is in a pending
local transaction. The Transaction property of the Command has not
been initialized."
This is the situation at the moment:
1) There is a webapplication with a lot of different methods that access
an Oracle database. These methods do not interact with each other, each
method performs its own tasks.
2) Some methods use a transaction, some execute only a single SQL
statement and therefore do not use a transaction.
When one user uses the application, everything works fine. There is no
error in code or transactions that do not work.
When other users start using the application at the same time, sometimes
the error mentioned before occurs. This error can occur in methods that
do not even have anything to do with methods that use transactions.
We use Oracle 10g as the database.
Sample of code:
public String NS_INFO_ESTUDO_TECNICO_MOD(StringDictionary strDict)
{
OpenConn();
OracleTransaction oTrans = connection.BeginTransaction(IsolationLevel.ReadCommitted);
OracleCommand command = connection.CreateCommand();
command.Transaction = oTrans;
command.CommandText = "GOMNET_PROJETOS.NS_INFO_ESTUDO_TECNICO_MOD";
command.CommandType = CommandType.StoredProcedure;
try
{
OracleParameter param30 = new OracleParameter("nCodigoError",OracleType.Number);
param30.Size = 1000;
param30.Direction = ParameterDirection.Output;
command.Parameters.Add(param30);
command.ExecuteNonQuery();
if (param30.Value.ToString() != "0")
{
oTrans.Rollback();
return ObtemMensagem(param30.Value.ToString());
}
else
{
oTrans.Commit();
}
return "0";
}
catch (Exception e)
{
throw e;
}
finally
{
command.Dispose();
}
}
This application has too much DB access without close connection. Use command.Dispose() in lot of methods.

How to roll back if all files have not been uploaded

Ok so i have a webform and 5 FileUpload control..a user can upload any number of files from 1 to 5 but if anyone of these files does not get uploaded then I want to rollback everything...
For ex:
if user has selected 4 files and if something unexpected occurs at 4th then I want to remove or rollback all the previous 3 file uploads..
I tried this..
try
{
using (TransactionScope scope = new TransactionScope())
{
dboperation dbinsert=new dboperation();
if (file1.ContentLength > 0)
{
.......
.......
dbo.insert(bytes, lastid, file2.FileName);
}
if (file2.ContentLength > 0)
{
.......
.......
dbo.insert(bytes, lastid, file2.FileName);
}
if (file3.ContentLength > 0)
{
.......
.......
dbo.insert(bytes, lastid, file2.FileName);
}//till ...file5
scope.Complete();
}//end of transactionscope
}
catch { }
'dboperation' is a class in c# file and 'dbinsert' is a method which is executing an insert stored procedure. My guess is that I need to use Transaction Scope but I am not sure if I am correct and even if I am how am I supposed to achieve this?
You need to implement transaction. You should start the transaction before inserting first one and catch any errors that occur. in case of error you have to rollback the transaction. And if all goes well you can commit your transaction.
You should also move you connection outside the dboperation or make a method in dboperation that takes connection from outside and uses that
for this you need to use Transaction something like this. I give you example.
class WithTransaction
{
public WithTransaction()
{
string FirstQuery = "INSERT INTO Table1 VALUES('Vineeth',24)";
string SecondQuery = "INSERT INTO Table2 VALUES('HisAddress')";
int ErrorVar = 0;
using (SqlConnection con = new SqlConnection("your connection string"))
{
try
{
SqlCommand ObjCommand = new SqlCommand(FirstQuery, con);
SqlTransaction trans;
con.Open();
trans = con.BeginTransaction();
ObjCommand.Transaction = trans;
//Executing first query
//What ever operation on your database do here
ObjCommand.ExecuteNonQuery(); //Exected first query
ObjCommand.CommandText = SecondQuery;
ObjCommand.ExecuteNonQuery(); //Exected first query
//Everything gone fine. So commiting
ObjCommand.Transaction.Commit();
}
catch (Exception ex)
{
Console.WriteLine("Error but we are rollbacking");
ObjCommand.Transaction.Rollback();
}
con.Close();
}
}
}
Or you can use TransactionScope
check this Link
TransactionScope
I hope this will help you.

Categories