Cant get TransactionScope working - c#

How can I use TransactionScope? I can hardly find any info about that. My project wont recognize TransactionScope and turns red when I try to call it. I tried with using System.Transactions.TransactionScope; but it didn't work either.
Also once its get worked, will Method_A(); to Method_C(); being within transaction then? Meaning if anything would fail e.g. in Method_C();, would everything rollback including Method_A();and Method_B();? That's the behavior I want.
private void method_A(){/* doing tons of db stuff */}
private void method_B(){/*...*/}
private void method_C(){/*...*/}
protected void Insert_OnClick(object sender, EventArgs e)
{
using(TransactionScope tran = new TransactionScope())
{
Method_A();
Method_B();
Method_C();
tran.Complete();
}
}
Using C#, ASP.NET and ms Access.

TransactionScope is not available for Microsoft Access, so you cannot use it.
Have a look at this question for alternative implementations of Transaction Scope.
As for the transactional scope, see this link
Relevant Quote:
Within one Workspace object, transactions are always global to the Workspace and aren't limited to only one Connection or Database object. If you perform operations on more than one connection or database within a Workspace transaction, resolving the transaction (that is, using the CommitTrans or Rollback method) affects all operations on all connections and databases within that workspace.
This means that everything you do on the Access-File within your workspace is within the transaction, even if you access the workspace from somewhere else while the transaction is still going.
Keep this in mind:
The behavior of transactions with Access databases differs from the behavior of ODBC data sources, such as Microsoft SQL Server. For example, if a database is connected to a file server, and the file server stops before a transaction has had time to commit its changes, then your database could be left in an inconsistent state. If you require true transaction support with respect to durability, you should investigate using a client/server architecture.

Related

Roll Back Insert SQL Server [duplicate]

Say I'm having a Windows Form application which connected to n databases, with n connections opened simultaneously.
What I'm looking for is to do a transaction with all of those databases in one go.
For example if I were to have 2 database connections :
using (ITransaction tx1 = session1.OpenTransaction())
{
using (ITransaction tx2 = session2.OpenTransaction())
{
// Do the query thingy here
}
}
Writing all that is fine at first, but things get kind of redundant when I wanted to query here and there, and not to mention the possibility to adding a new connection.
What I wanted is to loop all of the registered session and wrap it up in a service, probably something like this :
class TransactionManager
{
private ISession[] _sessions;
public TransactionManager(string[] connectionStrings)
{
// Initialize the sessions here
}
public function DoTransaction(string query)
{
foreach (ISession session in _sessions)
{
// What to do here? Using? Try-catch?
}
}
}
If I were to use using in the foreach loop, it would mean that if connection A successful but connection B wasn't, then only connection B would be rolled back.
It seems you may be re-inventing TransactionScope. Doing all this under a unit of work is straightforward*:
using (TransactionScope scope = new TransactionScope())
{
... Do Stuff with Connection 1 using SqlDataReader
... Do Stuff with Connection 2 using Entity Framework
... Do Stuff with Connection 3 on another Oracle Database
... And for good measure do some stuff in MSMQ or other DTC resource
scope.Complete(); // If you are happy
}
Stuff doesn't need to be inline at all - it can be in a different class, or a different assembly. There's no need to explicitly register database or queue connections with the TransactionScope - everything happens automagically, provided that the resources you use are able to enlist into an ambient transaction.
Now the small print:
* Any time you use more than one database connection concurrently, or different connection strings, or multiple technologies, this will require 2 phase commit and escalate to a Distributed transaction in order to ensure ACID across the resources. MSDTC itself has lots more small print and poses many more challenges in a corporate network, like firewalls, clustering, security configuration and bugs.
However, with Lightweight transactions on MS Sql Server, if you can keep all your connections using the same database and same
connection string settings, and close each connection before opening
the next, then you can avoid
DTC.
Distributed Transactions are complex - you will need to install and configure the MSDTC service on your app server, and all distributed resources will need to have MSDTC or equivalent (e.g. XA, LUA) configured.
MSDTC isn't yet fully supported on .Net Core
Maintaining a transaction across multiple ACID resources will invariably maintain locks on these resources, until the transaction is committed or rolled back. This often doesn't make for good neighbourliness in a high volume enterprise, so be sure to consider the consequences of the locking.
If the Stuff is done across multiple threads, you'll need to rope in DependentTransaction
A last point worth mentioning is the default isolation level with TransactionScope is Serializable, which is prone to deadlocks. In most non-critical scenarios you'll probably be able drop this down to Read Committed.
use TransactionScope, it will take care of committing or rolling back all included transactions:
using (var ts = new TransactionScope())
{
... // your old code
ts.Complete()
}

Why is DbContext.Database.CurrentTransaction always null?

Is there anyway to find if a DbContext is enlisted in any transaction while enlist=false in the connection string?
I was tracing DbContext.Database.CurrentTransaction, but I noticed it is always null.
I know when enlist=false, all opened connections will not enlist themselves in an ambient transaction, is that right?
If (2) is correct, how to enlist DbContext in an transaction where TransactionScope is used?
Finally, I noticed using clones of DependentTransaction with multiple DbContext and multiple threads while enlist=false will not promote the transaction to distributed one, but I wonder am I still able to commit and rollback in case an exception happened using the dependent transaction while enlist=false?
if (4) is incorrect, then is there any way to fully avoid DistributedTransaction while being able to open multiple connections with a single transaction scope?
FYI, currently Oracle database is employed; however, in future MySQL is going to be in operation as well.
Thank you
I cant really say something to 1 , 2 and 3.. But:
The distribution-thing is not absolutely clear to me. But however, MS escalates Transactions from LTM (Lightweigt Transaction Manger) to DTC if a some criteria come to play. For Example if you try to access different databases in one transaction..
The escalation from LTM to DTC or the decission if an escalation will be forced is a system-decission. Until now I didnt find a way to change this behaviour. Thats why you need to think about the transactions in general. If there is a possibility to avoid multiple-database access you may rethink your transactions.
For further information I´ll recommend Why is my TransactionScope trying to use MSDTC when used in an EF Code First app? , MSSQL Error 'The underlying provider failed on Open' and How do I use TransactionScope in C#?

Transaction Scope giving underlying connection failed to open

For LINQ i am using TransactionScope to handle transactions. When i execute the queries i get an exception.
Underlying connection failed to Open.
and the inner exception is saying something about DTC. I read online that i will have to enable some service on the server. But i donot want to do that. How can i use transcactions without enabling DTC. My code is something like this
public void function1()
{
using(TransactionScope t = new TransactionScope())
{
RunSomeSelectQueries();
RunSomeInsertQueries();
RunSomeUpdate Queries();
t.Complete();
}
}
Thanks in advance.
You have a serious problem in you tx handling that will push al ot of load into various levels.
TransactioNScope is nice, but
Calling methods that open separate connections WITHOUT NEED is bad.
Here is why:
If a Tx has one connection, it is handled in the kernel as local transaciton scope.
If you have multiple connections (transacted ressources) you need DTC.
And:
DTC is much slower than just a connection, with a lot more load on the server (multiple open connections - they have to stay open until the transaction commits). Also that turns into a multi step commit - generally a lot of overhead and making things slower.
That generally is a "hey, I just use transactions" antipattern.
Properly you should make sure you only create one database connection UNLESS YOU NEED MORE THAN ONE (like multiple databases are involved) so that the transaction scope does not proppagate to the DTC for having multiple ressources.
Obviously you also should configure DTC correctly IF you need it, but again: in this case the real problem is that you abuse the transaction scope forcing a DTC propagation where none is actually needed.

How do I minimize or inform users of database connection lag / failure?

I'm maintaining a ASP/C# program that uses an MS SQL Server 2008 R2 for its database requirements.
On normal and perfect days, everything works fine as it is. But we don't live in a perfect world.
An Application (for Leave, Sick Leave, Overtime, Undertime, etc.) Approval process requires up to ten separate connections to the database. The program connects to the database, passes around some relevant parameters, and uses stored procedures to do the job. Ten times.
Now, due to the structure of the entire thing, which I can not change, a dip in the connection, or heck, if I put a debug point in VS2005 and let it hang there long enough, the Application Approval Process goes incomplete. The tables are often just joined together, so a data mismatch - a missing data here, a primary key that failed to update there - would mean an entire row would be useless.
Now, I know that there is nothing I can do to prevent this - this is a connection issue, after all.
But are there ways to minimize connection lag / failure? Or a way to inform the users that something went wrong with the process? A rollback changes feature (either via program, or SQL), so that any incomplete data in the database will be undone?
Thanks.
But are there ways to minimize connection lag / failure? Or a way to
inform the users that something went wrong with the process? A
rollback changes feature (either via program, or SQL), so that any
incomplete data in the database will be undone?
As we discussed in the comments, transactions will address many of your concerns.
A transaction comprises a unit of work performed within a database
management system (or similar system) against a database, and treated
in a coherent and reliable way independent of other transactions.
Transactions in a database environment have two main purposes:
To provide reliable units of work that allow correct recovery from failures and keep a database consistent even in cases of system
failure, when execution stops (completely or partially) and many
operations upon a database remain uncompleted, with unclear status.
To provide isolation between programs accessing a database concurrently. If this isolation is not provided, the program's outcome
are possibly erroneous.
Source
Transactions in .Net
As you might expect, the database is integral to providing transaction support for database-related operations. However, creating transactions from your business tier is quite easy and allows you to use a single transaction across multiple database calls.
Quoting from my answer here:
I see several reasons to control transactions from the business tier:
Communication across data store boundaries. Transactions don't have to be against a RDBMS; they can be against a variety of entities.
The ability to rollback/commit transactions based on business logic that may not be available to the particular stored procedure you are calling.
The ability to invoke an arbitrary set of queries within a single transaction. This also eliminates the need to worry about transaction count.
Personal preference: c# has a more elegant structure for declaring transactions: a using block. By comparison, I've always found transactions inside stored procedures to be cumbersome when jumping to rollback/commit.
Transactions are most easily declared using the TransactionScope (reference) abstraction which does the hard work for you.
using( var ts = new TransactionScope() )
{
// do some work here that may or may not succeed
// if this line is reached, the transaction will commit. If an exception is
// thrown before this line is reached, the transaction will be rolled back.
ts.Complete();
}
Since you are just starting out with transactions, I'd suggest testing out a transaction from your .Net code.
Call a stored procedure that performs an INSERT.
After the INSERT, purposely have the procedure generate an error of any kind.
You can validate your implementation by seeing that the INSERT was rolled back automatically.
Transactions in the Database
Of course, you can also declare transactions inside a stored procedure (or any sort of TSQL statement). See here for more information.
If you use the same SQLConnection, or other connection types that implement IDbConnection, you can do something similar to transactionscopes but without the need to create the security risk that is a transactionscope.
In VB:
Using scope as IDbTransaction = mySqlCommand.Connection.BeginTransaction()
If blnEverythingGoesWell Then
scope.Commit()
Else
scope.Rollback()
End If
End Using
If you don't specify commit, the default is to rollback the transaction.

Transaction Scope in details with so many transaction and its advantage

I am having more then 20 transaction in in one shot. I want to use transaction scope with this. Is it possible? And If possible then what is the advantage of using transacation scope class over simple transaction.
What is the best practice to use transaction scope?
The advantages of TransactionScope are:
you don't have to pass a transaction around (ADO.NET should enlist automatically)
which means that you can even use a TransactionScope to add transactions to existing, closed-source code (i.e. no changes are required)
a TransactionScope can (via DTC) span multiple resources (i.e. multiple databases, or a database and an MSMQ server, etc)
But you pay for this a little bit with speed. A connection-based transaction is slightly quicker (not much), but can only span a single resource and needs to be attached manually to all your DAL code. However, if you only talk to a single SQL2005/SQL2008 instance, then it can use the "LTM" - meaning it doesn't have to involve DTC (which is where most of the performance cost comes from) unless it absolutely needs to. Many TransactionScope operations can therefore complete talking only to the database.
If you want to span 20 operations, then TransactionScope should be ideal - it'll save you having to pass the transactions around, and allow each operation to manage their connection locally - making for highly re-usable code. Indeed, TransactionScope can be nested in the ways you expect, so you can have:
void Deposit(...) { /* uses TranScope to do a deposit */ }
void Debit(...) { /* uses TranScope to do a debit */ }
void Transfer(...) { /* uses a TranScope to span Debit/Deposit */ }
To do this using database transactions you'd need to pass the connection and transaction objects to each method, which quickly gets ungainly - especially if you need to code to work with/without an existing open transaction (lots of "if(tran==null)" etc).
For more information, see Transactions in .net

Categories