c# – Alternative to TransactionScope

Question:

I'm using Entity Framework (version 4.4) in an AspNet MVC project with somewhat old .NET Framework (version 4.0) and SQL Server .

I don't have access to the server where the application is hosted, and from time to time it suffers some migrations to other servers, so I was advised to avoid using techniques that make it necessary for some extra resource (which is not by default).

I'm developing a feature in the application that needs a transaction, but by default EF closes the connection when calling SaveChanges() , and so I get an exception when I try to make any new request through my Entities object, I get the following exception:

The underlying provider failed Open.

I then tried to instantiate my context at different times for each change, but the same error persists.

using(TransactionScope ts = new System.Transactions.TransactionScope())
{
    var teste1 = new Teste();
    using (var context = new MyEntities())
    {
        teste1.Nome = "Teste1";
        context.Add(teste1);
        context.SaveChanges();
    }

    // Até aqui tudo está funcionando bem!

    using (var context = new MyEntities())
    {
        //Erro nessa linha!
        var usuario = context.User.SingleOrDefault(u => u.UserId == ViewSessionContext.UserId);

        if(usuario != null)
        {
           var teste2 = new FilhoTeste();
           teste2.Nome = "FilhoTeste";
           teste2.TesteId = teste1.Id;
           teste2.UserId = usuario.Id;
           teste2.Add(teste2);
           context.SaveChanges();
        }
    }

    ts.Complete();

}

Would it be possible to use a transaction without having to enable DTC ?

I also tried to force the connection to open but got the same error!

Search sources:

Answer:

There is no need to open two contexts within a transaction scope. Do this using the same context:

using (var ts = new System.Transactions.TransactionScope())
{
    using (var context = new MyEntities())
    {
        var teste1 = context.Teste.SingleOrDefault(t => t.Id = 1);
        teste1.Nome = "Teste1";
        context.Entry(teste1).State = EntityState.Modified;

        var teste2 = context.Teste.SingleOrDefault(t => t.Id = 2);
        teste2.Nome = "Teste2";
        context.Entry(teste2).State = EntityState.Modified;

        context.SaveChanges();
    }

    ts.Complete();
}

The reasoning is analogous when there is dependency between objects:

using (var ts = new System.Transactions.TransactionScope())
{
    var teste1 = new Teste();
    using (var context = new MyEntities())
    {
        teste1.Nome = "Teste1";
        context.Add(teste1);
        context.SaveChanges();

        var usuario = context.User.SingleOrDefault(u => u.UserId == ViewSessionContext.UserId);

        if(usuario != null)
        {
           var teste2 = new FilhoTeste();
           teste2.Nome = "FilhoTeste";
           teste2.TesteId = teste1.Id;
           teste2.UserId = usuario.Id;
           teste2.Add(teste2);

           context.SaveChanges();
        }
    }

    ts.Complete();    
}
Scroll to Top