Operações assíncronas do Entity Framework 6 e TranscationScope

Pesquisei no stackoverflow, mas não consegui encontrar uma pergunta semelhante, aponte-me se já houver uma.

Eu estava tentando implementar um repositório reutilizável genérico com operações de sincronização e assíncrona, mas com meu pouco conhecimento sobre o Entity Framework e a Unidade de trabalho, estou lutando para encontrar a maneira correta de implementá-lo.

Eu adicionei algumas variações na operação SaveAndCommit, mas não sei qual é a melhor maneira de fazer isso com transação e assíncrona.

----Editar----

De acordo com meu entendimento, as transações devem ser usadas quando mais de uma operação é executada, mas, para fins de entendimento, eu a usei para uma operação. (Por favor me corrija se eu estiver errado)

Isto é o que eu fiz até agora

public class Service<TEntity> : IService<TEntity>
    where TEntity : Entity
{
    #region Constructor and Properties

    UnitOfWork _unitOfWork { get { return UnitOfWork.UnitOfWorkPerHttpRequest; } }

    protected DbSet<TEntity> Entities
    {
        get { return _unitOfWork.Set<TEntity>(); }
    }

    #endregion Constructor and Properties


    #region Operations

    public virtual IQueryable<TEntity> QueryableEntities()
    {
        return Entities;
    }

    public virtual async Task<IList<TEntity>> WhereAsync(Expression<Func<TEntity, bool>> predicate)
    {
        return await Entities.Where(predicate).ToListAsync();
    }

    public virtual IList<TEntity> Where(Expression<Func<TEntity, bool>> predicate)
    {
        return Entities.Where(predicate).ToList();
    }

    public virtual async Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> predicate)
    {
        return await Entities.FirstOrDefaultAsync(predicate);
    }

    public virtual TEntity FirstOrDefault(Expression<Func<TEntity, bool>> predicate)
    {
        return Entities.FirstOrDefault(predicate);
    }

    public virtual async Task<TEntity> GetByIdAsync(int id)
    {
        return await Entities.FindAsync(id);
    }

    public virtual TEntity GetById(int id)
    {
        return Entities.Find(id);
    }

    // Method to the change the EntityState
    public virtual void Save(TEntity entity)
    {
        if (entity.Id == 0)
        {
            Entities.Add(entity);
        }
        else
        {
            _unitOfWork.Entry(entity).State = EntityState.Modified;
        }
    }

    #region Need clarification here

    // Uses transaction scope to commit the entity and dispose automatically
    // call rollback but this is not async and don't have any async
    // functions (Or I could not find)
    public virtual void SaveAndCommit(TEntity entity)
    {
        using (var transaction = _unitOfWork.BeginTransaction())
        {
            try
            {
                Save(entity);
                transaction.Commit();
            }
            catch (DbEntityValidationException e)
            {
            }
        }
    }

    // This is asynchronous but don't uses transaction
    public virtual async Task SaveAndCommitAsync(TEntity entity)
    {
        try
        {
            Save(entity);
            await _unitOfWork.SaveChangesAsync();
        }
        catch (DbEntityValidationException e)
        {
        }
    }

    // Tried to mix async and transaction but don't know if it will actually         
    // work or correct way of doing this
    public virtual async Task SaveAndCommitWithTransactionAsync(TEntity entity)
    {
        using (var transaction = _unitOfWork.BeginTransaction())
        {
            try
            {
                Save(entity);
                await _unitOfWork.SaveChangesAsync();
            }
            catch (DbEntityValidationException e)
            {
                transaction.Rollback();
            }
        }
    }

    #endregion Need clarification here

    public virtual async Task DeleteAsync(TEntity entity)
    {
        if (entity == null) return;

        Entities.Remove(entity);
        await _unitOfWork.SaveChangesAsync();
    }

    //All similar methods for delete as for Save

    public virtual async Task<int> CountAsync(Expression<Func<TEntity, bool>> predicate = null)
    {
        if (predicate != null)
        {
            return await Entities.CountAsync(predicate);
        }

        return await Entities.CountAsync();
    }

    #endregion Operations

}

Por favor, me guie e sugira a melhor maneira de conseguir isso.

Agora parece que a maneira correta de implementar um escopo de transação com chamada assíncrona seria

public virtual async Task SaveAndCommitWithTransactionAsync(TEntity entity)
    {
        using (var transaction = _unitOfWork.BeginTransaction())
        {
                Save(entity);
                await _unitOfWork.SaveChangesAsync();

                // Still no changes made to database
                transaction.Commit();

               //Rollback will automatically be called by using in dispose method
        }
    }

ReferênciasReferência do MSDN

Blog com descrição mais clara

visualstudiomagazine.com Para: quando você chama SaveChanges, nenhuma das suas alterações entra em vigor até você chamar o método de Confirmação do objeto Transaction

questionAnswers(1)

yourAnswerToTheQuestion