Error in Transactionscope

Asked

Viewed 77 times

2

I’m trying to accomplish a TransactionScope but it always gives me a mistake:

Server Error in Application '/'.

A Second Operation Started on this context before a Previous asynchronous Operation completed. Use 'await' to ensure that any asynchronous Operations have completed before Calling Another method on this context. Any instance Members are not Guaranteed to be thread safe.

Description: An untreated exception occurred during the execution of current web request. Examine stack tracking to get more information about the error and where it originated in the code.

Exception Details: System.Notsupportedexception: A Second Operation Started on this context before a Previous asynchronous Operation completed. Use 'await' to ensure that any asynchronous Operations have completed before Calling Another method on this context. Any instance Members are not Guaranteed to be thread safe.

Error of Origin:

Line 150: { line 151: Client = await db.Clientes.Singleasync(x => x.Clienteid == id); Line 152:
Title = await db.Titulos.Where(t => t.Tituloid == client.Titulo.Tituloid). Firstordefaultasync(); Line 153:
db.Titulos.Remove(title); Line 154: await db.Savechangesasync();

My code in the controller where I do it, is the following:

[HttpPost, ActionName("Excluir")]
public async Task<ActionResult> ConfirmarExclusao(Guid id)
{
    using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
    {
        Cliente cliente = await db.Clientes.SingleAsync(x => x.ClienteId == id);
        Titulo titulo = await db.Titulos.Where(t => t.TituloId == cliente.Titulo.TituloId).FirstOrDefaultAsync();
        db.Titulos.Remove(titulo);
        await db.SaveChangesAsync();

        db.Clientes.Remove(cliente);
        await db.SaveChangesAsync();
        scope.Complete();
        return RedirectToAction("Indice");
    }
}

Unlike the code above, I tried to use the ConfigureAwait(); on the lines:

Cliente cliente = await db.Clientes.SingleAsync(x => x.ClienteId == id).ConfigureAwait(false);
Titulo titulo = await db.Titulos.Where(t => t.TituloId == cliente.Titulo.TituloId).FirstOrDefaultAsync().ConfigureAwait(false);

But it didn’t work.

What causes this mistake?

What I do to fix?

This is the best way to solve this problem ?

1 answer

2


What causes this mistake?

Note that here you use as parameter an aggregate class that has not yet been loaded (cliente.Titulo):

Titulo titulo = await db.Titulos.Where(t => t.TituloId == cliente.Titulo.TituloId).FirstOrDefaultAsync();

That is, when you are running this part, the Entity Framework is going to the database Titulo by lazy load, just what you are selecting. Note that at this point in the code cliente.Titulo is not yet loaded.

What I do to fix?

Hurry the load on the top line and don’t use the bottom line to load:

        using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
        {
            var cliente = await db.Clientes
                                 .Include(c => c.Titulo)
                                 .FirstOrDefaultAsync(c => c.ClienteId == id);//.ConfigureAwait(false);

            // Este não precisa mais.
            // db.Titulos.Remove(titulo);
            // await db.SaveChangesAsync();

            db.Clientes.Remove(cliente);
            await db.SaveChangesAsync();

            scope.Complete();
            return RedirectToAction("Indice");
        }

This is the best way to solve this problem?

Yes, because you are asking the Entity Framework to observe Cliente and your Titulo before erasing them.

Browser other questions tagged

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