コード例 #1
0
        public static async Task <DbDataReader> ExecuteReaderAsync(IReadOnlyList <IMySqlCommand> commands, ICommandPayloadCreator payloadCreator, CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            var commandListPosition = new CommandListPosition(commands);
            var command             = commands[0];

            // pre-requisite: Connection is non-null must be checked before calling this method
            var connection = command.Connection !;

            if (Log.IsDebugEnabled())
            {
                Log.Debug("Session{0} ExecuteReader {1} CommandCount: {2}", connection.Session.Id, ioBehavior, commands.Count);
            }

            Dictionary <string, CachedProcedure?>?cachedProcedures = null;

            foreach (var command2 in commands)
            {
                if (command2.CommandType == CommandType.StoredProcedure)
                {
                    cachedProcedures ??= new Dictionary <string, CachedProcedure?>();
                    var commandText = command2.CommandText !;
                    if (!cachedProcedures.ContainsKey(commandText))
                    {
                        cachedProcedures.Add(commandText, await connection.GetCachedProcedure(ioBehavior, commandText, cancellationToken).ConfigureAwait(false));

                        // because the connection was used to execute a MySqlDataReader with the connection's DefaultCommandTimeout,
                        // we need to reapply the command's CommandTimeout (even if some of the time has elapsed)
                        command.CancellableCommand.ResetCommandTimeout();
                    }
                }
            }

            var writer = new ByteBufferWriter();

            // cachedProcedures will be non-null if there is a stored procedure, which is also the only time it will be read
            if (!payloadCreator.WriteQueryCommand(ref commandListPosition, cachedProcedures !, writer))
            {
                throw new InvalidOperationException("ICommandPayloadCreator failed to write query payload");
            }

            cancellationToken.ThrowIfCancellationRequested();

            using var payload      = writer.ToPayloadData();
            using var registration = command.CancellableCommand.RegisterCancel(cancellationToken);
            connection.Session.StartQuerying(command.CancellableCommand);
            command.SetLastInsertedId(-1);
            try
            {
                await connection.Session.SendAsync(payload, ioBehavior, CancellationToken.None).ConfigureAwait(false);

                return(await MySqlDataReader.CreateAsync(commandListPosition, payloadCreator, cachedProcedures, command, behavior, ioBehavior, cancellationToken).ConfigureAwait(false));
            }
            catch (MySqlException ex) when(ex.Number == (int)MySqlErrorCode.QueryInterrupted && cancellationToken.IsCancellationRequested)
            {
                Log.Warn("Session{0} query was interrupted", connection.Session.Id);
                throw new OperationCanceledException(cancellationToken);
            }
            catch (Exception ex) when(payload.Span.Length > 4_194_304 && (ex is SocketException || ex is IOException || ex is MySqlProtocolException))
            {
                // the default MySQL Server value for max_allowed_packet (in MySQL 5.7) is 4MiB: https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_max_allowed_packet
                // use "decimal megabytes" (to round up) when creating the exception message
                int megabytes = payload.Span.Length / 1_000_000;

                throw new MySqlException("Error submitting {0}MB packet; ensure 'max_allowed_packet' is greater than {0}MB.".FormatInvariant(megabytes), ex);
            }
        }
コード例 #2
0
        public static async Task <DbDataReader> ExecuteReaderAsync(IReadOnlyList <IMySqlCommand> commands, ICommandPayloadCreator payloadCreator, CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            var commandListPosition = new CommandListPosition(commands);
            var command             = commands[0];

            if (Log.IsDebugEnabled())
            {
                Log.Debug("Session{0} ExecuteReader {1} CommandCount: {2}", command.Connection.Session.Id, ioBehavior, commands.Count);
            }

            Dictionary <string, CachedProcedure> cachedProcedures = null;

            foreach (var command2 in commands)
            {
                if (command2.CommandType == CommandType.StoredProcedure)
                {
                    if (cachedProcedures is null)
                    {
                        cachedProcedures = new Dictionary <string, CachedProcedure>();
                    }
                    if (!cachedProcedures.ContainsKey(command2.CommandText))
                    {
                        cachedProcedures.Add(command2.CommandText, await command2.Connection.GetCachedProcedure(ioBehavior, command2.CommandText, cancellationToken).ConfigureAwait(false));
                    }
                }
            }

            var writer = new ByteBufferWriter();

            if (!payloadCreator.WriteQueryCommand(ref commandListPosition, cachedProcedures, writer))
            {
                throw new InvalidOperationException("ICommandPayloadCreator failed to write query payload");
            }

            cancellationToken.ThrowIfCancellationRequested();

            using (var payload = writer.ToPayloadData())
                using (command.CancellableCommand.RegisterCancel(cancellationToken))
                {
                    command.Connection.Session.StartQuerying(command.CancellableCommand);
                    command.SetLastInsertedId(-1);
                    try
                    {
                        await command.Connection.Session.SendAsync(payload, ioBehavior, CancellationToken.None).ConfigureAwait(false);

                        return(await MySqlDataReader.CreateAsync(commandListPosition, payloadCreator, cachedProcedures, command, behavior, ioBehavior, cancellationToken).ConfigureAwait(false));
                    }
                    catch (MySqlException ex) when(ex.Number == (int)MySqlErrorCode.QueryInterrupted && cancellationToken.IsCancellationRequested)
                    {
                        Log.Warn("Session{0} query was interrupted", command.Connection.Session.Id);
                        throw new OperationCanceledException(cancellationToken);
                    }
                    catch (Exception ex) when(payload.ArraySegment.Count > 4_194_304 && (ex is SocketException || ex is IOException || ex is MySqlProtocolException))
                    {
                        // the default MySQL Server value for max_allowed_packet (in MySQL 5.7) is 4MiB: https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_max_allowed_packet
                        // use "decimal megabytes" (to round up) when creating the exception message
                        int megabytes = payload.ArraySegment.Count / 1_000_000;

                        throw new MySqlException("Error submitting {0}MB packet; ensure 'max_allowed_packet' is greater than {0}MB.".FormatInvariant(megabytes), ex);
                    }
                }
        }