Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

368
Vistas
How to nest transactions in EF Core 6?

I am already using transactions inside my repository functions in some cases because I sometimes need to insert data into two tables at once and I want the whole operation to fail if one of the inserts fails.

Now I ran into a situation where I had to wrap calls to multiple repositories / functions in another transaction, but when one of those functions already uses a transaction internally I will get the error The connection is already in a transaction and cannot participate in another transaction. I do not want to remove the transaction from the repository function because this would mean that I have to know for which repository functions a transaction is required which I would then have to implement in the service layer. On the other hand, it seems like I cannot use repository functions in a transaction when they already use a transaction internally. Here is an example for where I am facing this problem:

// Reverse engineered classes
public partial class TblProject
{
    public TblProject()
    {
        TblProjectStepSequences = new HashSet<TblProjectStepSequence>();
    }
    
    public int ProjectId { get; set; }

    public virtual ICollection<TblProjectStepSequence> TblProjectStepSequences { get; set; }
}

public partial class TblProjectTranslation
{
    public int ProjectId { get; set; }
    public string Language { get; set; }
    public string ProjectName { get; set; }

    public virtual TblProject Project { get; set; }
}

public partial class TblProjectStepSequence
{
    public int SequenceId { get; set; }
    public int ProjectId { get; set; }
    public int StepId { get; set; }
    public int SequencePosition { get; set; }

    public virtual TblStep Step { get; set; }
    public virtual TblProject Project { get; set; }
}

// Creating a project in the ProjectRepository
public async Task<int> CreateProjectAsync(TblProject project, ...)
{
    using (var transaction = this.Context.Database.BeginTransaction())
    {
        await this.Context.TblProjects.AddAsync(project);
        await this.Context.SaveChangesAsync();
        // Insert translations... (project Id is required for this)
        await this.Context.SaveChangesAsync();
        transaction.Commit();
        
        return entity.ProjectId;
    }
}

// Creating the steps for a project in the StepRepository
public async Task<IEnumerable<int>> CreateProjectStepsAsync(int projectId, IEnumerable<TblProjectStepSequence> steps)
{
    await this.Context.TblProjectStepSequences.AddRangeAsync(steps);
    await this.Context.SaveChangesAsync();

    return steps.Select(step =>
    {
        return step.SequenceId;
    }
    );
}

// Creating a project with its steps in the service layer
public async Task<int> CreateProjectWithStepsAsync(TblProject project, IEnumerable<TblProjectStepSequence> steps)
{
    // This is basically a wrapper around Database.BeginTransaction() and IDbContextTransaction
    using (Transaction transaction = await transactionService.BeginTransactionAsync())
    {
        int projectId = await projectRepository.CreateProjectAsync(project);
        await stepRepository.CreateProjectStepsAsync(projectId, steps);

        return projectId;
    }
}

Is there a way how I can nest multiple transactions inside each other without already knowing in the inner transactions that there could be an outer transaction? I know that it might not be possible to actually nest those transactions from a technical perspective but I still need a solution which either uses the internal transaction of the repository or the outer one (if one exists) so there is no way how I could accidentally forget to use a transaction for repository functions which require one.

over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

You could check the CurrentTransaction property and do something like this:

var transaction = Database.CurrentTransaction ?? Database.BeginTransaction()

If there is already a transaction use that, otherwise start a new one...

Edit: Removed the Using block, see comments. More logic is needed for Committing/Rollback the transcaction though...

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda