async Task SendToInstance <T>(SagaQueryConsumeContext <TSaga, T> context, DbContext dbContext, ISagaPolicy <TSaga, T> policy, TSaga instance,
                                      IPipe <SagaConsumeContext <TSaga, T> > next)
            where T : class
        {
            try
            {
                var sagaConsumeContext = new EntityFrameworkSagaConsumeContext <TSaga, T>(dbContext, context, instance);

                sagaConsumeContext.LogUsed();

                await policy.Existing(sagaConsumeContext, next).ConfigureAwait(false);
            }
            catch (SagaException)
            {
                throw;
            }
            catch (Exception ex)
            {
                throw new SagaException(ex.Message, typeof(TSaga), typeof(T), instance.CorrelationId, ex);
            }
        }
        async Task SendLogic <T>(IDbContextTransaction transaction, DbContext dbContext, ConsumeContext <T> context, ISagaPolicy <TSaga, T> policy,
                                 IPipe <SagaConsumeContext <TSaga, T> > next)
            where T : class
        {
            var sagaId = context.CorrelationId.Value;

            if (policy.PreInsertInstance(context, out var instance))
            {
                var inserted = await PreInsertSagaInstance(dbContext, context, instance).ConfigureAwait(false);

                if (!inserted)
                {
                    instance = null; // Reset this back to null if the insert failed. We will use the MissingPipe to create instead
                }
            }

            try
            {
                if (instance == null)
                {
                    IQueryable <TSaga> queryable = QuerySagas(dbContext);

                    // Query with a row Lock instead using FromSql. Still a single trip to the DB (unlike EF6, which has to make one dummy call to row lock)
                    var rowLockQuery = _rawSqlLockStatements?.GetRowLockStatement <TSaga>(dbContext);
                    if (rowLockQuery != null)
                    {
                        instance = await queryable.FromSql(rowLockQuery, new object[] { sagaId }).SingleOrDefaultAsync(context.CancellationToken)
                                   .ConfigureAwait(false);
                    }
                    else
                    {
                        instance = await queryable.SingleOrDefaultAsync(x => x.CorrelationId == sagaId, context.CancellationToken).ConfigureAwait(false);
                    }
                }

                if (instance == null)
                {
                    var missingSagaPipe = new MissingPipe <T>(dbContext, next);

                    await policy.Missing(context, missingSagaPipe).ConfigureAwait(false);
                }
                else
                {
                    var sagaConsumeContext = new EntityFrameworkSagaConsumeContext <TSaga, T>(dbContext, context, instance);

                    sagaConsumeContext.LogUsed();

                    await policy.Existing(sagaConsumeContext, next).ConfigureAwait(false);
                }

                await dbContext.SaveChangesAsync(context.CancellationToken).ConfigureAwait(false);

                transaction.Commit();
            }
            catch (DbUpdateConcurrencyException)
            {
                try
                {
                    transaction.Rollback();
                }
                catch (Exception innerException)
                {
                    LogContext.Warning?.Log(innerException, "Transaction rollback failed");
                }

                throw;
            }
            catch (DbUpdateException ex)
            {
                if (IsDeadlockException(ex))
                {
                    // deadlock, no need to rollback
                }
                else
                {
                    context.LogFault(this, ex, instance?.CorrelationId);

                    try
                    {
                        transaction.Rollback();
                    }
                    catch (Exception innerException)
                    {
                        LogContext.Warning?.Log(innerException, "Transaction rollback failed");
                    }
                }

                throw;
            }
            catch (Exception ex)
            {
                context.LogFault(this, ex, instance?.CorrelationId);

                try
                {
                    transaction.Rollback();
                }
                catch (Exception innerException)
                {
                    LogContext.Warning?.Log(innerException, "Transaction rollback failed");
                }

                throw;
            }
        }