Alternative to the Transactionscope

Asked

Viewed 399 times

3

I’m using Entity Framework (version 4.4) in a project Aspnet MVC with .NET Framework a little old (version 4.0) and SQL Server.

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

I am developing a functionality in the application that needs a transaction, but by default the EF closes the connection in the call of the SaveChanges(), and thus receive a exception when trying to make any new request through my object Entities receive the following Exception:

The underlying provider failed in 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();

}

It would be possible to use a transaction without having to enable the DTC?

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

Research sources:

  • What is DatabaseEntityModel and what his need?

  • sorry, it was my mistake when editing the example. I made the correction in the question.

1 answer

2

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();
}

Reasoning is analogous when there is dependence 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();    
}
  • In your case you are using Savechanges for the two created objects, in my case I depend on Object1 created to be able to create Object2. I will re-edit my example in the question.

  • Edited! I think now I gave a better idea of my context...

  • I’ve already edited the answer. It’s the same thing, almost.

  • Your DTC is enabled?

  • It usually comes enabled by default. It just doesn’t come on very old machines.

  • Unfortunately this is my case. DTC is disabled and I have no way to enable it...

Show 1 more comment

Browser other questions tagged

You are not signed in. Login or sign up in order to post.