コード例 #1
0
ファイル: BatchExecutor.cs プロジェクト: lodejard/AllNetCore
        public virtual async Task <int> ExecuteAsync(
            IEnumerable <ModificationCommandBatch> commandBatches,
            IRelationalConnection connection,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            var rowsAffected = 0;
            await connection.OpenAsync(cancellationToken);

            IDbContextTransaction startedTransaction = null;

            try
            {
                if (connection.CurrentTransaction == null)
                {
                    startedTransaction = connection.BeginTransaction();
                }

                foreach (var commandbatch in commandBatches)
                {
                    await commandbatch.ExecuteAsync(connection, cancellationToken);

                    rowsAffected += commandbatch.ModificationCommands.Count;
                }

                startedTransaction?.Commit();
            }
            finally
            {
                startedTransaction?.Dispose();
                connection.Close();
            }

            return(rowsAffected);
        }
コード例 #2
0
        public virtual async Task<int> ExecuteAsync(
            IEnumerable<ModificationCommandBatch> commandBatches,
            IRelationalConnection connection,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            var rowsAffected = 0;
            await connection.OpenAsync(cancellationToken);
            IRelationalTransaction startedTransaction = null;
            try
            {
                if (connection.Transaction == null)
                {
                    startedTransaction = connection.BeginTransaction();
                }

                foreach (var commandbatch in commandBatches)
                {
                    await commandbatch.ExecuteAsync(connection, cancellationToken);
                    rowsAffected += commandbatch.ModificationCommands.Count;
                }

                startedTransaction?.Commit();
            }
            finally
            {
                startedTransaction?.Dispose();
                connection.Close();
            }

            return rowsAffected;
        }
コード例 #3
0
        public virtual async Task <object> ExecuteAsync(
            IRelationalConnection connection,
            Func <Task <object> > action,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            Check.NotNull(connection, nameof(connection));

            var connectionWasOpen = connection.DbConnection.State == ConnectionState.Open;

            if (!connectionWasOpen)
            {
                Logger.OpeningConnection(connection.ConnectionString);

                await connection.OpenAsync(cancellationToken);
            }

            try
            {
                return(await action());
            }
            finally
            {
                if (!connectionWasOpen)
                {
                    Logger.ClosingConnection(connection.ConnectionString);

                    connection.Close();
                }
            }
        }
コード例 #4
0
        protected override async Task <object> ExecuteAsync(IRelationalConnection connection, string executeMethod, IReadOnlyDictionary <string, object> parameterValues, bool closeConnection, CancellationToken cancellationToken = default(CancellationToken))
        {
            ThrowIf.Argument.IsNull(connection, nameof(connection));
            ThrowIf.Argument.IsNull(executeMethod, nameof(executeMethod));

            var    dbCommand = CreateCommand(connection, parameterValues);
            object result    = null;

            await connection.OpenAsync(cancellationToken);

            if (executeMethod.Equals(nameof(ExecuteReader)))
            {
                try
                {
                    result = new RelationalDataReader(connection,
                                                      dbCommand,
                                                      new MySQLDataReader(await((MySqlCommand)dbCommand).ExecuteReaderAsync(cancellationToken) as MySqlDataReader));
                    return(result);
                }
                catch
                {
                    dbCommand.Dispose();
                    throw;
                }
            }

            return(await base.ExecuteAsync(connection, executeMethod, parameterValues, closeConnection, cancellationToken));
        }
コード例 #5
0
        public virtual async Task ExecuteNonQueryAsync(
            IRelationalConnection connection,
            IEnumerable <RelationalCommand> relationalCommands,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            Check.NotNull(connection, nameof(connection));
            Check.NotNull(relationalCommands, nameof(relationalCommands));

            await connection.OpenAsync(cancellationToken);

            try
            {
                foreach (var command in relationalCommands)
                {
                    await ExecuteAsync(
                        connection,
                        command,
                        async c => await c.ExecuteNonQueryAsync(cancellationToken),
                        cancellationToken);
                }
            }
            finally
            {
                connection.Close();
            }
        }
コード例 #6
0
        /// <summary>
        ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
        ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
        ///     any release. You should only use it directly in your code with extreme caution and knowing that
        ///     doing so can result in application failures when updating to a new Entity Framework Core release.
        /// </summary>
        public virtual async Task ExecuteNonQueryAsync(
            IEnumerable <MigrationCommand> migrationCommands,
            IRelationalConnection connection,
            CancellationToken cancellationToken = default)
        {
            Check.NotNull(migrationCommands, nameof(migrationCommands));
            Check.NotNull(connection, nameof(connection));

            var transactionScope = new TransactionScope(TransactionScopeOption.Suppress, TransactionScopeAsyncFlowOption.Enabled);

            try
            {
                await connection.OpenAsync(cancellationToken);

                try
                {
                    IDbContextTransaction transaction = null;

                    try
                    {
                        foreach (var command in migrationCommands)
                        {
                            if (transaction == null &&
                                !command.TransactionSuppressed)
                            {
                                transaction = await connection.BeginTransactionAsync(cancellationToken);
                            }

                            if (transaction != null &&
                                command.TransactionSuppressed)
                            {
                                transaction.Commit();
                                await transaction.DisposeAsync();

                                transaction = null;
                            }

                            await command.ExecuteNonQueryAsync(connection, cancellationToken : cancellationToken);
                        }

                        transaction?.Commit();
                    }
                    finally
                    {
                        if (transaction != null)
                        {
                            await transaction.DisposeAsync();
                        }
                    }
                }
                finally
                {
                    await connection.CloseAsync();
                }
            }
            finally
            {
                await transactionScope.DisposeAsyncIfAvailable();
            }
        }
コード例 #7
0
        public virtual async Task <object> ExecuteAsync(
            [NotNull] IRelationalConnection connection,
            [NotNull] Func <Task <object> > action,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            Check.NotNull(connection, nameof(connection));

            // TODO Deal with suppressing transactions etc.

            var connectionWasOpen = connection.DbConnection.State == ConnectionState.Open;

            if (!connectionWasOpen)
            {
                Logger.OpeningConnection(connection.ConnectionString);

                await connection.OpenAsync(cancellationToken).WithCurrentCulture();
            }

            try
            {
                return(await action().WithCurrentCulture());
            }
            finally
            {
                if (!connectionWasOpen)
                {
                    Logger.ClosingConnection(connection.ConnectionString);

                    connection.Close();
                }
            }
        }
コード例 #8
0
        public static async Task ExecuteNonQueryAsync(
            [NotNull] this IEnumerable <IRelationalCommand> commands,
            [NotNull] IRelationalConnection connection,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            Check.NotNull(commands, nameof(commands));
            Check.NotNull(connection, nameof(connection));

            await connection.OpenAsync(cancellationToken);

            try
            {
                foreach (var command in commands)
                {
                    await command.ExecuteNonQueryAsync(
                        connection,
                        manageConnection : false,
                        cancellationToken : cancellationToken);
                }
            }
            finally
            {
                connection.Close();
            }
        }
コード例 #9
0
        public virtual async Task <IReadOnlyList <HistoryRow> > GetAppliedMigrationsAsync(
            CancellationToken cancellationToken = default(CancellationToken))
        {
            var rows = new List <HistoryRow>();

            if (await ExistsAsync(cancellationToken))
            {
                await _connection.OpenAsync(cancellationToken);

                try
                {
                    using (var reader = await _executor.ExecuteReaderAsync(_connection, GetAppliedMigrationsSql, cancellationToken))
                    {
                        while (await reader.ReadAsync(cancellationToken))
                        {
                            rows.Add(new HistoryRow(reader.GetString(0), reader.GetString(1)));
                        }
                    }
                }
                finally
                {
                    _connection.Close();
                }
            }

            return(rows);
        }
コード例 #10
0
        public async Task <int> ExecuteAsync(
            IEnumerable <ModificationCommandBatch> commandBatches,
            IRelationalConnection connection,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            var registrosAfetados = 0;
            await connection.OpenAsync(cancellationToken, false).ConfigureAwait(false);

            FirebirdSqlRelationalTransaction startedTransaction = null;

            try
            {
                if (connection.CurrentTransaction == null)
                {
                    startedTransaction = await(connection as FirebirdSqlRelationalConnection).BeginTransactionAsync(cancellationToken).ConfigureAwait(false) as FirebirdSqlRelationalTransaction;
                }


                foreach (var commandbatch in commandBatches)
                {
                    await commandbatch.ExecuteAsync(connection, cancellationToken).ConfigureAwait(false);

                    registrosAfetados += commandbatch.ModificationCommands.Count;
                }

                if (startedTransaction != null)
                {
                    await startedTransaction.CommitAsync(cancellationToken).ConfigureAwait(false);
                }

                startedTransaction?.Dispose();
            }
            catch (Exception err)
            {
                try
                {
                    startedTransaction?.Rollback();
                    startedTransaction?.Dispose();
                }
                catch
                {
                    // if the connection was lost, rollback command will fail.  prefer to throw original exception in that case
                }
                throw err;
            }
            finally
            {
                connection.Close();
            }
            return(registrosAfetados);
        }
コード例 #11
0
        public async Task <int> ExecuteAsync(
            IEnumerable <ModificationCommandBatch> commandBatches,
            IRelationalConnection connection,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            var rowsAffected = 0;
            await connection.OpenAsync(cancellationToken, false).ConfigureAwait(false);

            MySqlRelationalTransaction startedTransaction = null;

            try
            {
                if (connection.CurrentTransaction == null)
                {
                    // ReSharper disable once PossibleNullReferenceException
                    startedTransaction = await(connection as MySqlRelationalConnection).BeginTransactionAsync(cancellationToken).ConfigureAwait(false) as MySqlRelationalTransaction;
                }

                foreach (var commandbatch in commandBatches)
                {
                    await commandbatch.ExecuteAsync(connection, cancellationToken).ConfigureAwait(false);

                    rowsAffected += commandbatch.ModificationCommands.Count;
                }

                if (startedTransaction != null)
                {
                    await startedTransaction.CommitAsync(cancellationToken).ConfigureAwait(false);
                }
                startedTransaction?.Dispose();
            }
            catch
            {
                try
                {
                    startedTransaction?.Rollback();
                    startedTransaction?.Dispose();
                }
                catch
                {
                    // if the connection was lost, rollback command will fail.  prefer to throw original exception in that case
                }
                throw;
            }
            finally
            {
                connection.Close();
            }

            return(rowsAffected);
        }
コード例 #12
0
        public async Task <int> ExecuteAsync(
            IEnumerable <ModificationCommandBatch> commandBatches,
            IRelationalConnection connection,
            CancellationToken cancellationToken = default)
        {
            var RowsAffecteds = 0;

            FbRelationalTransaction currentTransaction = null;

            try
            {
                if (connection?.DbConnection?.State != System.Data.ConnectionState.Open)
                {
                    await connection.OpenAsync(cancellationToken, false).ConfigureAwait(false);
                }

                if (connection.CurrentTransaction == null)
                {
                    currentTransaction =
                        await((FbRelationalConnection)connection)
                        .BeginTransactionAsync(cancellationToken).ConfigureAwait(false) as FbRelationalTransaction;
                }

                foreach (var commandbatch in commandBatches)
                {
                    await commandbatch.ExecuteAsync(connection, cancellationToken).ConfigureAwait(false);

                    RowsAffecteds += commandbatch.ModificationCommands.Count;
                }

                if (currentTransaction != null)
                {
                    await currentTransaction.CommitAsync(cancellationToken).ConfigureAwait(false);
                }

                currentTransaction?.Dispose();
            }
            catch (Exception err)
            {
                currentTransaction?.Rollback();
                currentTransaction?.Dispose();

                throw err;
            }
            finally
            {
                connection?.Close();
            }
            return(RowsAffecteds);
        }
コード例 #13
0
        /// <summary>
        ///     This API supports the Entity Framework Core infrastructure and is not intended to be used
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        public virtual async Task <int> ExecuteAsync(
            IEnumerable <ModificationCommandBatch> commandBatches,
            IRelationalConnection connection,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            var rowsAffected = 0;
            await connection.OpenAsync(cancellationToken);

            IDbContextTransaction startedTransaction = null;

            try
            {
                if (connection.CurrentTransaction == null)
                {
                    startedTransaction = connection.BeginTransaction();
                }

                foreach (var commandbatch in commandBatches)
                {
                    await commandbatch.ExecuteAsync(connection, cancellationToken);

                    // Fixed Issue #1: DataReader conflicted when added multiple entities
                    try
                    {
                        lock (this)
                        {
                            var reader = (connection.DbConnection as MySqlConnection).Reader.LastOrDefault();
                            if (reader != null)
                            {
                                reader.Dispose();
                                (connection.DbConnection as MySqlConnection).Reader.Remove(reader);
                            }
                        }
                    }
                    catch
                    {
                    }
                    rowsAffected += commandbatch.ModificationCommands.Count;
                }

                startedTransaction?.Commit();
            }
            finally
            {
                startedTransaction?.Dispose();
                connection.Close();
            }

            return(rowsAffected);
        }
コード例 #14
0
        /// <summary>
        ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
        ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
        ///     any release. You should only use it directly in your code with extreme caution and knowing that
        ///     doing so can result in application failures when updating to a new Entity Framework Core release.
        /// </summary>
        public virtual async Task <int> ExecuteAsync(
            IEnumerable <ModificationCommandBatch> commandBatches,
            IRelationalConnection connection,
            CancellationToken cancellationToken = default)
        {
            var rowsAffected = 0;
            IDbContextTransaction startedTransaction = null;

            try
            {
                if (connection.CurrentTransaction == null &&
                    (connection as ITransactionEnlistmentManager)?.EnlistedTransaction == null &&
                    Transaction.Current == null &&
                    CurrentContext.Context.Database.AutoTransactionsEnabled)
                {
                    startedTransaction = await connection.BeginTransactionAsync(cancellationToken);
                }
                else
                {
                    await connection.OpenAsync(cancellationToken);
                }

                foreach (var batch in commandBatches)
                {
                    await batch.ExecuteAsync(connection, cancellationToken);

                    rowsAffected += batch.ModificationCommands.Count;
                }

                if (startedTransaction != null)
                {
                    await startedTransaction.CommitAsync(cancellationToken);
                }
            }
            finally
            {
                if (startedTransaction != null)
                {
                    await startedTransaction.DisposeAsync();
                }
                else
                {
                    await connection.CloseAsync();
                }
            }

            return(rowsAffected);
        }
コード例 #15
0
        /// <summary>
        ///     This API supports the Entity Framework Core infrastructure and is not intended to be used 
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        public virtual async Task ExecuteNonQueryAsync(
            IEnumerable<MigrationCommand> migrationCommands,
            IRelationalConnection connection,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            Check.NotNull(migrationCommands, nameof(migrationCommands));
            Check.NotNull(connection, nameof(connection));

            await connection.OpenAsync(cancellationToken);

            try
            {
                IDbContextTransaction transaction = null;

                try
                {
                    foreach (var command in migrationCommands)
                    {
                        if (transaction == null
                            && !command.TransactionSuppressed)
                        {
                            transaction = await connection.BeginTransactionAsync(cancellationToken);
                        }

                        if (transaction != null
                            && command.TransactionSuppressed)
                        {
                            transaction.Commit();
                            transaction.Dispose();
                            transaction = null;
                        }

                        await command.ExecuteNonQueryAsync(connection, cancellationToken: cancellationToken);
                    }

                    transaction?.Commit();
                }
                finally
                {
                    transaction?.Dispose();
                }
            }
            finally
            {
                connection.Close();
            }
        }
コード例 #16
0
        /// <summary>
        ///     This API supports the Entity Framework Core infrastructure and is not intended to be used 
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        public virtual async Task<int> ExecuteAsync(
            IEnumerable<ModificationCommandBatch> commandBatches,
            IRelationalConnection connection,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            var rowsAffected = 0;
            await connection.OpenAsync(cancellationToken);
            IDbContextTransaction startedTransaction = null;
            try
            {
                if (connection.CurrentTransaction == null)
                {
                    startedTransaction = connection.BeginTransaction();
                }

                foreach (var commandbatch in commandBatches)
                {
                    await commandbatch.ExecuteAsync(connection, cancellationToken);
                    // Fixed Issue #1: DataReader conflicted when added multiple entities
                    try
                    {
                        lock(this)
                        {
                            var reader = (connection.DbConnection as MySqlConnection).Reader.LastOrDefault();
                            if (reader != null)
                            {
                                reader.Dispose();
                                (connection.DbConnection as MySqlConnection).Reader.Remove(reader);
                            }
                        }
                    }
                    catch
                    {
                    }
                    rowsAffected += commandbatch.ModificationCommands.Count;
                }

                startedTransaction?.Commit();
            }
            finally
            {
                startedTransaction?.Dispose();
                connection.Close();
            }

            return rowsAffected;
        }
コード例 #17
0
        protected virtual async Task <object> ExecuteAsync(
            IRelationalConnection connection,
            Func <Task <object> > action,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            Check.NotNull(connection, nameof(connection));

            await connection.OpenAsync(cancellationToken);

            try
            {
                return(await action());
            }
            finally
            {
                connection.Close();
            }
        }
コード例 #18
0
        protected virtual async Task<object> ExecuteAsync(
            IRelationalConnection connection,
            Func<Task<object>> action,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            Check.NotNull(connection, nameof(connection));

            await connection.OpenAsync(cancellationToken);

            try
            {
                return await action();
            }
            finally
            {
                connection.Close();
            }
        }
コード例 #19
0
        public virtual async Task <int> ExecuteAsync(
            [NotNull] IEnumerable <ModificationCommandBatch> commandBatches,
            [NotNull] IRelationalConnection connection,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            Check.NotNull(commandBatches, nameof(commandBatches));
            Check.NotNull(connection, nameof(connection));

            var rowsAffected = 0;
            await connection.OpenAsync(cancellationToken).WithCurrentCulture();

            RelationalTransaction startedTransaction = null;

            try
            {
                if (connection.Transaction == null)
                {
                    startedTransaction = connection.BeginTransaction();
                }

                foreach (var commandbatch in commandBatches)
                {
                    rowsAffected += await commandbatch.ExecuteAsync(
                        connection.Transaction,
                        _typeMapper,
                        _context,
                        Logger, cancellationToken)
                                    .WithCurrentCulture();
                }

                startedTransaction?.Commit();
            }
            finally
            {
                startedTransaction?.Dispose();
                connection.Close();
            }

            return(rowsAffected);
        }
コード例 #20
0
        protected virtual async Task <T> ExecuteAsync <T>(
            [NotNull] IRelationalConnection connection,
            [NotNull] RelationalCommand command,
            [NotNull] Func <DbCommand, Task <T> > action,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            await connection.OpenAsync(cancellationToken);

            try
            {
                using (var dbCommand = command.CreateCommand(connection))
                {
                    Logger.LogCommand(dbCommand);

                    return(await action(dbCommand));
                }
            }
            finally
            {
                connection.Close();
            }
        }
コード例 #21
0
        public virtual async Task<int> ExecuteAsync(
            IEnumerable<ModificationCommandBatch> commandBatches,
            IRelationalConnection connection,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            Check.NotNull(commandBatches, nameof(commandBatches));
            Check.NotNull(connection, nameof(connection));

            var rowsAffected = 0;
            await connection.OpenAsync(cancellationToken);
            RelationalTransaction startedTransaction = null;
            try
            {
                if (connection.Transaction == null)
                {
                    startedTransaction = connection.BeginTransaction();
                }

                foreach (var commandbatch in commandBatches)
                {
                    rowsAffected += await commandbatch.ExecuteAsync(
                        connection.Transaction,
                        _typeMapper,
                        _context,
                        Logger, cancellationToken);
                }

                startedTransaction?.Commit();
            }
            finally
            {
                startedTransaction?.Dispose();
                connection.Close();
            }

            return rowsAffected;
        }
コード例 #22
0
        /// <summary>
        ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
        ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
        ///     any release. You should only use it directly in your code with extreme caution and knowing that
        ///     doing so can result in application failures when updating to a new Entity Framework Core release.
        /// </summary>
        public virtual async Task <int> ExecuteAsync(
            IEnumerable <ModificationCommandBatch> commandBatches,
            IRelationalConnection connection,
            CancellationToken cancellationToken = default)
        {
            var rowsAffected     = 0;
            var transaction      = connection.CurrentTransaction;
            var beganTransaction = false;
            var createdSavepoint = false;

            try
            {
                if (transaction == null &&
                    (connection as ITransactionEnlistmentManager)?.EnlistedTransaction == null &&
                    Transaction.Current == null &&
                    CurrentContext.Context.Database.AutoTransactionsEnabled)
                {
                    transaction = await connection.BeginTransactionAsync(cancellationToken);

                    beganTransaction = true;
                }
                else
                {
                    await connection.OpenAsync(cancellationToken);

                    if (transaction?.AreSavepointsSupported == true)
                    {
                        await transaction.SaveAsync(SavepointName, cancellationToken);

                        createdSavepoint = true;
                    }
                }

                foreach (var batch in commandBatches)
                {
                    await batch.ExecuteAsync(connection, cancellationToken);

                    rowsAffected += batch.ModificationCommands.Count;
                }

                if (beganTransaction)
                {
                    await transaction.CommitAsync(cancellationToken);
                }
            }
            catch
            {
                if (createdSavepoint)
                {
                    await transaction.RollbackAsync(SavepointName, cancellationToken);
                }

                throw;
            }
            finally
            {
                if (createdSavepoint)
                {
                    await transaction.ReleaseAsync(SavepointName, cancellationToken);
                }
                else if (beganTransaction)
                {
                    await transaction.DisposeAsync();
                }
                else
                {
                    await connection.CloseAsync();
                }
            }

            return(rowsAffected);
        }
コード例 #23
0
        /// <summary>
        ///     This API supports the Entity Framework Core infrastructure and is not intended to be used
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        protected virtual async Task <object> ExecuteAsync(
            [NotNull] IRelationalConnection connection,
            [NotNull] string executeMethod,
            [CanBeNull] IReadOnlyDictionary <string, object> parameterValues,
            bool closeConnection = true,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            Check.NotNull(connection, nameof(connection));
            Check.NotEmpty(executeMethod, nameof(executeMethod));

            var dbCommand = CreateCommand(connection, parameterValues);

            await connection.OpenAsync(cancellationToken);

            var startTimestamp = Stopwatch.GetTimestamp();
            var instanceId     = Guid.NewGuid();

            DiagnosticSource.WriteCommandBefore(
                dbCommand,
                executeMethod,
                instanceId,
                startTimestamp,
                async: true);

            object result;

            try
            {
                switch (executeMethod)
                {
                case nameof(ExecuteNonQuery):
                {
                    using (dbCommand)
                    {
                        result = await dbCommand.ExecuteNonQueryAsync(cancellationToken);
                    }

                    break;
                }

                case nameof(ExecuteScalar):
                {
                    using (dbCommand)
                    {
                        result = await dbCommand.ExecuteScalarAsync(cancellationToken);
                    }

                    break;
                }

                case nameof(ExecuteReader):
                {
                    try
                    {
                        result = new RelationalDataReader(
                            connection,
                            dbCommand,
                            await dbCommand.ExecuteReaderAsync(cancellationToken));
                    }
                    catch
                    {
                        dbCommand.Dispose();

                        throw;
                    }

                    break;
                }

                default:
                {
                    throw new NotSupportedException();
                }
                }

                var currentTimestamp = Stopwatch.GetTimestamp();

                Logger.LogCommandExecuted(dbCommand, startTimestamp, currentTimestamp);

                DiagnosticSource.WriteCommandAfter(
                    dbCommand,
                    executeMethod,
                    instanceId,
                    startTimestamp,
                    currentTimestamp,
                    async: true);

                if (closeConnection)
                {
                    connection.Close();
                }
            }
            catch (Exception exception)
            {
                var currentTimestamp = Stopwatch.GetTimestamp();

                Logger.LogCommandExecuted(dbCommand, startTimestamp, currentTimestamp);

                DiagnosticSource.WriteCommandError(
                    dbCommand,
                    executeMethod,
                    instanceId,
                    startTimestamp,
                    currentTimestamp,
                    exception,
                    async: true);

                connection.Close();

                throw;
            }
            finally
            {
                dbCommand.Parameters.Clear();
            }

            return(result);
        }
コード例 #24
0
ファイル: BatchExecutor.cs プロジェクト: yangmaomao86/efcore
        /// <summary>
        ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
        ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
        ///     any release. You should only use it directly in your code with extreme caution and knowing that
        ///     doing so can result in application failures when updating to a new Entity Framework Core release.
        /// </summary>
        public virtual async Task <int> ExecuteAsync(
            IEnumerable <ModificationCommandBatch> commandBatches,
            IRelationalConnection connection,
            CancellationToken cancellationToken = default)
        {
            var rowsAffected     = 0;
            var transaction      = connection.CurrentTransaction;
            var beganTransaction = false;
            var createdSavepoint = false;

            try
            {
                if (transaction == null &&
                    (connection as ITransactionEnlistmentManager)?.EnlistedTransaction == null &&
                    Transaction.Current == null &&
                    CurrentContext.Context.Database.AutoTransactionsEnabled)
                {
                    transaction = await connection.BeginTransactionAsync(cancellationToken).ConfigureAwait(false);

                    beganTransaction = true;
                }
                else
                {
                    await connection.OpenAsync(cancellationToken).ConfigureAwait(false);

                    if (transaction?.SupportsSavepoints == true &&
                        CurrentContext.Context.Database.AutoSavepointsEnabled)
                    {
                        await transaction.CreateSavepointAsync(SavepointName, cancellationToken).ConfigureAwait(false);

                        createdSavepoint = true;
                    }
                }

                foreach (var batch in commandBatches)
                {
                    await batch.ExecuteAsync(connection, cancellationToken).ConfigureAwait(false);

                    rowsAffected += batch.ModificationCommands.Count;
                }

                if (beganTransaction)
                {
                    await transaction.CommitAsync(cancellationToken).ConfigureAwait(false);
                }
            }
            catch
            {
                if (createdSavepoint && connection.DbConnection.State == ConnectionState.Open)
                {
                    try
                    {
                        await transaction.RollbackToSavepointAsync(SavepointName, cancellationToken).ConfigureAwait(false);
                    }
                    catch (Exception e)
                    {
                        UpdateLogger.BatchExecutorFailedToRollbackToSavepoint(CurrentContext.GetType(), e);
                    }
                }

                throw;
            }
            finally
            {
                if (beganTransaction)
                {
                    await transaction.DisposeAsync().ConfigureAwait(false);
                }
                else
                {
                    if (createdSavepoint)
                    {
                        if (connection.DbConnection.State == ConnectionState.Open)
                        {
                            try
                            {
                                await transaction.ReleaseSavepointAsync(SavepointName, cancellationToken).ConfigureAwait(false);
                            }
                            catch (Exception e)
                            {
                                UpdateLogger.BatchExecutorFailedToReleaseSavepoint(CurrentContext.GetType(), e);
                            }
                        }
                    }

                    await connection.CloseAsync().ConfigureAwait(false);
                }
            }

            return(rowsAffected);
        }
コード例 #25
0
        /// <summary>
        ///    The method called by other methods on this type to execute synchronously.
        /// </summary>
        /// <param name="connection"> The connection to use. </param>
        /// <param name="executeMethod"> The method type. </param>
        /// <param name="parameterValues"> The parameter values. </param>
        /// <param name="logger"> The command logger. </param>
        /// <param name="cancellationToken"> The cancellation token. </param>
        /// <returns> The result of the execution. </returns>
        protected virtual async Task <object> ExecuteAsync(
            [NotNull] IRelationalConnection connection,
            DbCommandMethod executeMethod,
            [CanBeNull] IReadOnlyDictionary <string, object> parameterValues,
            [CanBeNull] IDiagnosticsLogger <DbLoggerCategory.Database.Command> logger,
            CancellationToken cancellationToken = default)
        {
            Check.NotNull(connection, nameof(connection));

            var dbCommand = CreateCommand(connection, parameterValues);

            await connection.OpenAsync(cancellationToken);

            var commandId = Guid.NewGuid();

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

            logger?.CommandExecuting(
                dbCommand,
                executeMethod,
                commandId,
                connection.ConnectionId,
                async: true,
                startTime: startTime);

            object result;
            var    readerOpen = false;

            try
            {
                switch (executeMethod)
                {
                case DbCommandMethod.ExecuteNonQuery:
                {
                    result = await dbCommand.ExecuteNonQueryAsync(cancellationToken);

                    break;
                }

                case DbCommandMethod.ExecuteScalar:
                {
                    result = await dbCommand.ExecuteScalarAsync(cancellationToken);

                    break;
                }

                case DbCommandMethod.ExecuteReader:
                {
                    result = new RelationalDataReader(
                        connection,
                        dbCommand,
                        await dbCommand.ExecuteReaderAsync(cancellationToken),
                        commandId,
                        logger);
                    readerOpen = true;

                    break;
                }

                default:
                {
                    throw new NotSupportedException();
                }
                }

                logger?.CommandExecuted(
                    dbCommand,
                    executeMethod,
                    commandId,
                    connection.ConnectionId,
                    result,
                    true,
                    startTime,
                    stopwatch.Elapsed);
            }
            catch (Exception exception)
            {
                logger?.CommandError(
                    dbCommand,
                    executeMethod,
                    commandId,
                    connection.ConnectionId,
                    exception,
                    true,
                    startTime,
                    stopwatch.Elapsed);

                throw;
            }
            finally
            {
                if (!readerOpen)
                {
                    dbCommand.Parameters.Clear();
                    dbCommand.Dispose();
                    connection.Close();
                }
            }

            return(result);
        }
コード例 #26
0
        protected virtual async Task <object> ExecuteAsync(
            [NotNull] IRelationalConnection connection,
            [NotNull] string executeMethod,
            bool openConnection,
            bool closeConnection,
            CancellationToken cancellationToken = default(CancellationToken),
            [CanBeNull] IReadOnlyDictionary <string, object> parameterValues = null)
        {
            var dbCommand = CreateCommand(connection, parameterValues);

            WriteDiagnostic(
                RelationalDiagnostics.BeforeExecuteCommand,
                dbCommand,
                executeMethod,
                async: true);

            object result;

            if (openConnection)
            {
                await connection.OpenAsync(cancellationToken);
            }

            Stopwatch stopwatch = null;

            try
            {
                if (Logger.IsEnabled(LogLevel.Information))
                {
                    stopwatch = Stopwatch.StartNew();
                }

                switch (executeMethod)
                {
                case nameof(ExecuteNonQuery):
                {
                    using (dbCommand)
                    {
                        result = await dbCommand.ExecuteNonQueryAsync(cancellationToken);
                    }

                    break;
                }

                case nameof(ExecuteScalar):
                {
                    using (dbCommand)
                    {
                        result = await dbCommand.ExecuteScalarAsync(cancellationToken);
                    }

                    break;
                }

                case nameof(ExecuteReader):
                {
                    try
                    {
                        result
                            = new RelationalDataReader(
                                  openConnection ? connection : null,
                                  dbCommand,
                                  await dbCommand.ExecuteReaderAsync(cancellationToken));
                    }
                    catch
                    {
                        dbCommand.Dispose();

                        throw;
                    }

                    break;
                }

                default:
                {
                    throw new NotSupportedException();
                }
                }

                stopwatch?.Stop();

                Logger.LogCommandExecuted(dbCommand, stopwatch?.ElapsedMilliseconds);
            }
            catch (Exception exception)
            {
                stopwatch?.Stop();

                Logger.LogCommandExecuted(dbCommand, stopwatch?.ElapsedMilliseconds);

                DiagnosticSource
                .WriteCommandError(
                    dbCommand,
                    executeMethod,
                    async: true,
                    exception: exception);

                if (openConnection && !closeConnection)
                {
                    connection.Close();
                }

                throw;
            }
            finally
            {
                if (closeConnection)
                {
                    connection.Close();
                }
            }

            WriteDiagnostic(
                RelationalDiagnostics.AfterExecuteCommand,
                dbCommand,
                executeMethod,
                async: true);

            return(result);
        }
                /// <summary>
                /// 异步执行
                /// </summary>
                /// <param name="connection"></param>
                /// <param name="executeMethod"></param>
                /// <param name="parameterValues"></param>
                /// <param name="cancellationToken"></param>
                /// <returns></returns>
                protected override async Task <object> ExecuteAsync(IRelationalConnection connection, DbCommandMethod executeMethod, IReadOnlyDictionary <string, object> parameterValues, CancellationToken cancellationToken = default(CancellationToken))
                {
                    if (Check.IsTraceEnabled(Logger?.Logger))
                    {
                        Trace <DbLoggerCategory.Database.Command> .Write(Logger, LogLevel.Trace, OracleTraceTag.Entry, OracleTraceClassName.OracleRelationalCommand, OracleTraceFuncName.ExecuteAsync);
                    }
                    Check.NotNull(connection, nameof(connection));

                    // 创建命令并打开连接
                    DbCommand dbCommand = CreateCommand(connection, parameterValues);
                    await connection.OpenAsync(cancellationToken);

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

                    // 执行命令
                    Logger.CommandExecuting(dbCommand, executeMethod, commandId, connection.ConnectionId, async: true, startTime);

                    // 读取数据
                    bool readerOpen = false;

                    try
                    {
                        object obj;
                        switch (executeMethod)
                        {
                        case DbCommandMethod.ExecuteNonQuery:
                            obj = await dbCommand.ExecuteNonQueryAsync(cancellationToken);

                            break;

                        case DbCommandMethod.ExecuteScalar:
                            obj = await dbCommand.ExecuteScalarAsync(cancellationToken);

                            break;

                        case DbCommandMethod.ExecuteReader:
                        {
                            DbCommand command = dbCommand;
                            obj        = new RelationalDataReader(connection, command, await dbCommand.ExecuteReaderAsync(cancellationToken), commandId, Logger);
                            readerOpen = true;
                            break;
                        }

                        default:
                            throw new NotSupportedException();
                        }
                        Logger.CommandExecuted(dbCommand, executeMethod, commandId, connection.ConnectionId, obj, async: true, startTime, stopwatch.Elapsed);
                        return(obj);
                    }
                    catch (Exception ex)
                    {
                        if (Check.IsErrorEnabled(Logger?.Logger))
                        {
                            Trace <DbLoggerCategory.Database.Command> .Write(Logger, LogLevel.Error, OracleTraceTag.Error, OracleTraceClassName.OracleRelationalCommand, OracleTraceFuncName.ExecuteAsync, ex.ToString());
                        }
                        Logger.CommandError(dbCommand, executeMethod, commandId, connection.ConnectionId, ex, async: true, startTime, stopwatch.Elapsed);
                        throw;
                    }
                    finally
                    {
                        if (!readerOpen)
                        {
                            dbCommand.Dispose();
                            connection.Close();
                        }
                        dbCommand.Parameters.Clear();
                        if (Check.IsTraceEnabled(Logger?.Logger))
                        {
                            Trace <DbLoggerCategory.Database.Command> .Write(Logger, LogLevel.Trace, OracleTraceTag.Exit, OracleTraceClassName.OracleRelationalCommand, OracleTraceFuncName.ExecuteAsync);
                        }
                    }
                }
        private async Task <object> ExecuteAsync(
            IOBehavior ioBehavior,
            [NotNull] IRelationalConnection connection,
            [NotNull] string executeMethod,
            [CanBeNull] IReadOnlyDictionary <string, object> parameterValues,
            bool openConnection,
            bool closeConnection,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            Check.NotNull(connection, nameof(connection));
            Check.NotEmpty(executeMethod, nameof(executeMethod));
            var    dbCommand = CreateCommand(connection, parameterValues);
            object result;

            if (openConnection)
            {
                if (ioBehavior == IOBehavior.Asynchronous)
                {
                    await connection.OpenAsync(cancellationToken).ConfigureAwait(false);
                }
                else
                {
                    connection.Open();
                }
            }

            cancellationToken.ThrowIfCancellationRequested();
            var mySqlConnection = connection as MySqlRelationalConnection;
            var locked          = false;

            try
            {
                if (ioBehavior == IOBehavior.Asynchronous)
                {
                    // ReSharper disable once PossibleNullReferenceException
                    await mySqlConnection.PoolingOpenAsync(cancellationToken).ConfigureAwait(false);

                    await mySqlConnection.Lock.WaitAsync(cancellationToken).ConfigureAwait(false);
                }
                else
                {
                    // ReSharper disable once PossibleNullReferenceException
                    mySqlConnection.PoolingOpen();
                    mySqlConnection.Lock.Wait(cancellationToken);
                }
                locked = true;
                switch (executeMethod)
                {
                case nameof(ExecuteNonQuery):
                {
                    using (dbCommand)
                    {
                        if (ioBehavior == IOBehavior.Asynchronous)
                        {
                            result = await dbCommand.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false);
                        }
                        else
                        {
                            result = dbCommand.ExecuteNonQuery();
                        }
                    }
                    break;
                }

                case nameof(ExecuteScalar):
                {
                    using (dbCommand)
                    {
                        if (ioBehavior == IOBehavior.Asynchronous)
                        {
                            result = await dbCommand.ExecuteScalarAsync(cancellationToken).ConfigureAwait(false);
                        }
                        else
                        {
                            result = dbCommand.ExecuteScalar();
                        }
                    }
                    break;
                }

                case nameof(ExecuteReader):
                {
                    try
                    {
                        MySqlDataReader dataReader;
                        if (ioBehavior == IOBehavior.Asynchronous)
                        {
                            dataReader = await dbCommand.ExecuteReaderAsync(cancellationToken).ConfigureAwait(false) as MySqlDataReader;
                        }
                        else
                        {
                            dataReader = dbCommand.ExecuteReader() as MySqlDataReader;
                        }

                        result = new RelationalDataReader(openConnection ? connection : null, dbCommand,
                                                          new SynchronizedMySqlDataReader(dataReader, mySqlConnection));
                    }
                    catch (Exception)
                    {
                        dbCommand.Dispose();
                        throw;
                    }
                    break;
                }

                default:
                {
                    throw new NotSupportedException();
                }
                }
            }
            catch (Exception)
            {
                if (openConnection && !closeConnection)
                {
                    connection.Close();
                }
                throw;
            }
            finally
            {
                if (closeConnection)
                {
                    connection.Close();
                }
                if (locked && executeMethod != nameof(ExecuteReader))
                {
                    // if calling any other method, the command has finished executing and the lock can be released immediately
                    // ReSharper disable once PossibleNullReferenceException
                    mySqlConnection.Lock.Release();
                    mySqlConnection.PoolingClose();
                }
            }
            return(result);
        }
コード例 #29
0
        public virtual async Task<object> ExecuteAsync(
            IRelationalConnection connection,
            Func<Task<object>> action,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            Check.NotNull(connection, nameof(connection));

            var connectionWasOpen = connection.DbConnection.State == ConnectionState.Open;
            if (!connectionWasOpen)
            {
                Logger.OpeningConnection(connection.ConnectionString);

                await connection.OpenAsync(cancellationToken);
            }

            try
            {
                return await action();
            }
            finally
            {
                if (!connectionWasOpen)
                {
                    Logger.ClosingConnection(connection.ConnectionString);

                    connection.Close();
                }
            }
        }
コード例 #30
0
        /// <summary>
        ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
        ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
        ///     any release. You should only use it directly in your code with extreme caution and knowing that
        ///     doing so can result in application failures when updating to a new Entity Framework Core release.
        /// </summary>
        public virtual async Task ExecuteNonQueryAsync(
            IEnumerable <MigrationCommand> migrationCommands,
            IRelationalConnection connection,
            CancellationToken cancellationToken = default)
        {
            var userTransaction = connection.CurrentTransaction;

            if (userTransaction is not null && migrationCommands.Any(x => x.TransactionSuppressed))
            {
                throw new NotSupportedException(RelationalStrings.TransactionSuppressedMigrationInUserTransaction);
            }

            var transactionScope = new TransactionScope(TransactionScopeOption.Suppress, TransactionScopeAsyncFlowOption.Enabled);

            try
            {
                await connection.OpenAsync(cancellationToken).ConfigureAwait(false);

                try
                {
                    IDbContextTransaction?transaction = null;

                    try
                    {
                        foreach (var command in migrationCommands)
                        {
                            if (transaction == null &&
                                !command.TransactionSuppressed &&
                                userTransaction is null)
                            {
                                transaction = await connection.BeginTransactionAsync(cancellationToken)
                                              .ConfigureAwait(false);
                            }

                            if (transaction != null &&
                                command.TransactionSuppressed)
                            {
                                await transaction.CommitAsync(cancellationToken).ConfigureAwait(false);

                                await transaction.DisposeAsync().ConfigureAwait(false);

                                transaction = null;
                            }

                            await command.ExecuteNonQueryAsync(connection, cancellationToken : cancellationToken)
                            .ConfigureAwait(false);
                        }

                        if (transaction != null)
                        {
                            await transaction.CommitAsync(cancellationToken).ConfigureAwait(false);
                        }
                    }
                    finally
                    {
                        if (transaction != null)
                        {
                            await transaction.DisposeAsync().ConfigureAwait(false);
                        }
                    }
                }
                finally
                {
                    await connection.CloseAsync().ConfigureAwait(false);
                }
            }
            finally
            {
                await transactionScope.DisposeAsyncIfAvailable().ConfigureAwait(false);
            }
        }
コード例 #31
0
                // TODO: Copy and paste base code again in 3.0.
                //       Then replace "RelationalDataReader" with "MySqlConverterRelationalDataReader".
                // TODO: Remove entire method in 3.1.
                //       Replace with overridden implementation of "CreateRelationalDataReader".
                /// <summary>
                /// Uses the same code as in it's base class, except for returning a
                /// ConverterRelationalDataReader instead of a RelationalDataReader.
                /// </summary>
                protected override async Task <object> ExecuteAsync(
                    IRelationalConnection connection,
                    DbCommandMethod executeMethod,
                    IReadOnlyDictionary <string, object> parameterValues,
                    CancellationToken cancellationToken = default)
                {
                    if (connection == null)
                    {
                        throw new ArgumentNullException(nameof(connection));
                    }

                    var dbCommand = CreateCommand(connection, parameterValues);

                    await connection.OpenAsync(cancellationToken);

                    var commandId = Guid.NewGuid();

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

                    Logger.CommandExecuting(
                        dbCommand,
                        executeMethod,
                        commandId,
                        connection.ConnectionId,
                        async: true,
                        startTime: startTime);

                    object result;
                    var    readerOpen = false;

                    try
                    {
                        switch (executeMethod)
                        {
                        case DbCommandMethod.ExecuteNonQuery:
                        {
                            result = await dbCommand.ExecuteNonQueryAsync(cancellationToken);

                            break;
                        }

                        case DbCommandMethod.ExecuteScalar:
                        {
                            result = await dbCommand.ExecuteScalarAsync(cancellationToken);

                            break;
                        }

                        case DbCommandMethod.ExecuteReader:
                        {
                            result = new MySqlConverterRelationalDataReader(
                                connection,
                                dbCommand,
                                await dbCommand.ExecuteReaderAsync(cancellationToken),
                                commandId,
                                Logger);
                            readerOpen = true;

                            break;
                        }

                        default:
                        {
                            throw new NotSupportedException();
                        }
                        }

                        Logger.CommandExecuted(
                            dbCommand,
                            executeMethod,
                            commandId,
                            connection.ConnectionId,
                            result,
                            true,
                            startTime,
                            stopwatch.Elapsed);
                    }
                    catch (Exception exception)
                    {
                        Logger.CommandError(
                            dbCommand,
                            executeMethod,
                            commandId,
                            connection.ConnectionId,
                            exception,
                            true,
                            startTime,
                            stopwatch.Elapsed);

                        throw;
                    }
                    finally
                    {
                        if (!readerOpen)
                        {
                            dbCommand.Parameters.Clear();
                            dbCommand.Dispose();
                            connection.Close();
                        }
                    }

                    return(result);
                }
コード例 #32
0
        protected virtual async Task <T> ExecuteAsync <T>(
            [NotNull] IRelationalConnection connection,
            [NotNull] Func <DbCommand, IRelationalConnection, CancellationToken, Task <T> > action,
            [NotNull] string executeMethod,
            bool openConnection,
            bool closeConnection,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            var dbCommand = CreateCommand(connection);

            WriteDiagnostic(
                RelationalDiagnostics.BeforeExecuteCommand,
                dbCommand,
                executeMethod,
                async: true);

            T result;

            if (openConnection)
            {
                await connection.OpenAsync(cancellationToken);
            }

            Stopwatch stopwatch = null;

            try
            {
                if (Logger.IsEnabled(LogLevel.Information))
                {
                    stopwatch = Stopwatch.StartNew();
                }

                result = await action(dbCommand, connection, cancellationToken);

                stopwatch?.Stop();

                Logger.LogCommandExecuted(dbCommand, stopwatch?.ElapsedMilliseconds);
            }
            catch (Exception exception)
            {
                stopwatch?.Stop();

                Logger.LogCommandExecuted(dbCommand, stopwatch?.ElapsedMilliseconds);

                DiagnosticSource
                .WriteCommandError(
                    dbCommand,
                    executeMethod,
                    async: true,
                    exception: exception);

                if (openConnection && !closeConnection)
                {
                    connection.Close();
                }

                throw;
            }
            finally
            {
                if (closeConnection)
                {
                    connection.Close();
                }
            }

            WriteDiagnostic(
                RelationalDiagnostics.AfterExecuteCommand,
                dbCommand,
                executeMethod,
                async: true);

            return(result);
        }