public TResult ExecuteScalar <TResult>(Action <DbCommand> initializer)
        {
            if (unbufferedReader != null)
            {
                unbufferedReader.Buffer();
                unbufferedReader = null;
            }

            var connection = CurrentDbContext.Context.Database.GetService <IRelationalConnection>();

            connection.Open();

            using (var command = CreateCommand(connection))
            {
                initializer(command);

                var commandId = Guid.NewGuid();
                var startTime = DateTimeOffset.UtcNow;
                var stopwatch = Stopwatch.StartNew();

                logger.CommandExecuting(
                    command,
                    DbCommandMethod.ExecuteReader,
                    commandId,
                    connection.ConnectionId,
                    false,
                    startTime);

                try
                {
                    var result = command.ExecuteScalar();

                    logger.CommandExecuted(
                        command,
                        DbCommandMethod.ExecuteScalar,
                        commandId,
                        connection.ConnectionId,
                        result,
                        false,
                        startTime,
                        stopwatch.Elapsed);

                    return(DBNull.Value.Equals(result) ? default : (TResult)result);
                }
                catch (Exception exception)
                {
                    logger.CommandError(
                        command,
                        DbCommandMethod.ExecuteScalar,
                        commandId,
                        connection.ConnectionId,
                        exception,
                        false,
                        startTime,
                        stopwatch.Elapsed);

                    throw;
                }
                finally
                {
                    connection.Close();
                }
            }
        }
        public TResult ExecuteComplex <TResult>(Action <DbCommand> initializer, Func <DbDataReader, TResult> materializer)
        {
            if (unbufferedReader != null)
            {
                unbufferedReader.Buffer();
                unbufferedReader = null;
            }

            var result     = default(object);
            var connection = CurrentDbContext.Context.Database.GetService <IRelationalConnection>();

            connection.Open();

            using (var command = CreateCommand(connection))
            {
                initializer(command);

                var commandId = Guid.NewGuid();
                var startTime = DateTimeOffset.UtcNow;
                var stopwatch = Stopwatch.StartNew();

                logger.CommandExecuting(
                    command,
                    DbCommandMethod.ExecuteReader,
                    commandId,
                    connection.ConnectionId,
                    false,
                    startTime);

                try
                {
                    using (var reader = command.ExecuteReader(CommandBehavior.CloseConnection))
                    {
                        logger.CommandExecuted(
                            command,
                            DbCommandMethod.ExecuteReader,
                            commandId,
                            connection.ConnectionId,
                            result,
                            false,
                            startTime,
                            stopwatch.Elapsed);

                        reader.Read();

                        CurrentDbContext.GetDependencies().StateManager.BeginTrackingQuery();

                        return(materializer(reader));
                    }
                }
                catch (Exception exception)
                {
                    logger.CommandError(
                        command,
                        DbCommandMethod.ExecuteReader,
                        commandId,
                        connection.ConnectionId,
                        exception,
                        false,
                        startTime,
                        stopwatch.Elapsed);

                    throw;
                }
                finally
                {
                    connection.Close();
                }
            }
        }
        public IEnumerable <TElement> ExecuteEnumerable <TElement>(Action <DbCommand> initializer, Func <DbDataReader, TElement> materializer)
        {
            if (unbufferedReader != null)
            {
                unbufferedReader.Buffer();
                unbufferedReader = null;
            }

            var connection = CurrentDbContext.Context.Database.GetService <IRelationalConnection>();

            connection.Open();

            var command = CreateCommand(connection);

            initializer(command);

            var commandId = Guid.NewGuid();
            var startTime = DateTimeOffset.UtcNow;
            var stopwatch = Stopwatch.StartNew();

            logger.CommandExecuting(
                command,
                DbCommandMethod.ExecuteReader,
                commandId,
                connection.ConnectionId,
                false,
                startTime);

            var reader = default(DbDataReader);

            var caughtException = false;

            try
            {
                reader = command.ExecuteReader();

                logger.CommandExecuted(
                    command,
                    DbCommandMethod.ExecuteReader,
                    commandId,
                    connection.ConnectionId,
                    reader,
                    false,
                    startTime,
                    stopwatch.Elapsed);
            }
            catch (Exception exception)
            {
                caughtException = true;

                logger.CommandError(
                    command,
                    DbCommandMethod.ExecuteReader,
                    commandId,
                    connection.ConnectionId,
                    exception,
                    false,
                    startTime,
                    stopwatch.Elapsed);

                throw;
            }
            finally
            {
                if (caughtException)
                {
                    reader?.Dispose();
                    command.Dispose();
                    connection.Close();
                }
            }

            CurrentDbContext.GetDependencies().StateManager.BeginTrackingQuery();

            try
            {
                if (!connection.IsMultipleActiveResultSetsEnabled)
                {
                    var buffer = new BufferingDbDataReader(reader, ArrayPool <object> .Shared);

                    unbufferedReader = buffer;

                    reader = buffer;
                }

                while (reader.Read())
                {
                    yield return(materializer(reader));
                }
            }
            finally
            {
                if (unbufferedReader == reader)
                {
                    unbufferedReader = null;
                }

                reader?.Dispose();
                command.Dispose();
                connection.Close();
            }
        }