6

are there any alternative to transactionScope which does not need to enable DTC??

In the transaction I need to make two operations:

  1. Create one user (using membership - sql membership provider)
  2. Do one insert operation.
abatishchev
  • 98,240
  • 88
  • 296
  • 433
Pedre
  • 446
  • 1
  • 8
  • 16
  • 1
    In my experience setting `Enlist=false` in the connection string caused `TransactionScope` not to work at all; no updates were enlisted in the available `TransactionScope`. I verified this using a Standard SQL Trace that included Transaction Events against an Entity Framework 6 application. – Jean-Paul M Apr 21 '18 at 10:04

2 Answers2

11

TransactionScope uses the LTM - Lightweight Transaction Manager in .Net. Only if you open more than one connection in the same transaction or go between databases, should TransactionScope promote the transaction to the 2PC-based TX-manager, DTC.

For MS SQL Server 2008 and above, the DTC will become involved only if you are opening connections to different DBs. OR if you are opening connections in the same transactions from multiple threads EXCEPT if you are using DependentTransaction which is what you should enlist in your global transaction if you want to do threading.

As a side-point: I have some support for the multi-threading story in Castle.Transactions.

Side-point #2: If you use TransactionScope, make sure to declare the IsolationLevel explicitly otherwise you're serializing all your transactions (IsolationLevel.Serializable)!

Henrik
  • 9,714
  • 5
  • 53
  • 87
  • 3
    Almost right. Only if you open _different_ connections (SQL Server 2008+) will the transaction escalate (if you are using the same connection string, you will still be using the LTM). – Oded Jun 28 '12 at 11:44
  • @Pedre - For a _distributed_ transaction, you need a transaction manager. No if buts or maybes. – Oded Jun 28 '12 at 11:45
  • @Oded, yes it differs between version of SQL Server too. – Henrik Jun 28 '12 at 11:45
  • @MarcGravell - Not on the same DB/Server, as far as I have seen. – Oded Jun 28 '12 at 11:45
  • I think that 2005 was like I described and 2008 supports like Oded describes. – Henrik Jun 28 '12 at 11:46
  • @Pedre It might depend on your implementation of the membership provider. – Henrik Jun 28 '12 at 11:46
  • I think you can trigger DTC-ness through having multiple connections open in multiple threads, even if it's to the same DB, but if they are using the same transaction. – Henrik Jun 28 '12 at 11:48
  • @Henrik I am using System.Web.Security.MembershipProvider. is it correct? – Pedre Jun 28 '12 at 11:48
  • iirc, if several databases or nested connections are used, then transaction will be escalated to distributed. Correct? – abatishchev Jun 28 '12 at 11:49
  • @abatishchev I think it should be possible with Server 2008 to open two connections from the same thread for the same transaction, as they are pooled internally. – Henrik Jun 28 '12 at 11:51
  • A bit late to the party here, but @Henrik, you're saying you can avoid DTC when opening multiple connections from multiple threads to the same database in a single transaction by using DependentTransaction? From where do you have this information? I'm having trouble making that exact case work using SQL Server 2013, so starting to doubt this statement. :) – Anders Apr 10 '14 at 15:58
  • @Oded ***using the same connection string***, if I open different connections (SQL Server 2012) within `TransactionScope` the transaction escalate (DTC). Why ? – PreguntonCojoneroCabrón Jan 07 '18 at 22:44
2

Add Enlist=false in the connection string of your Membership.

connectionString="Data Source=xxx;Initial Catalog=xxx;Persist Security Info=True;User ID=xxx;Password=xxx;Enlist=false"

This is my use case:

using (TransactionScope tScope = new TransactionScope())
{
    MembershipCreateStatus createStatus;
    Membership.CreateUser(model.Email, model.Password, model.Email, null, null, true, model.Id, out createStatus);

    if (createStatus == MembershipCreateStatus.Success)
    {
       Roles.AddUserToRole(model.Email, "Administrator");
       _UpdatePersonnelAccess(model);
       _UpdatePersonnelHasAccess(model);
       _SendEmail_Welcome(model);
       PersonSessionLog.ManageSession(model);
    }
    else
       ViewBag.Message = "Error";

    tScope.Complete();
}

My application is published in Amazon EC2 while the database is in Amazon RDS. DTC is not supported in RDS that's why I also needed a way to prevent escalation to DTC. Btw, I am using SQL Server 2008 R2. I have 2 databases - ASPNETDB, data DB

Thanks to Paul post!

Kiquenet
  • 14,494
  • 35
  • 148
  • 243
danmbuen
  • 594
  • 5
  • 7