/// <summary>
        ///		Obtiene el datatable de una consulta
        /// </summary>
        internal async Task <DataTable> GetDataTableAsync(IDbProvider provider, string query, Models.ArgumentListModel arguments,
                                                          int actualPage, int pageSize, TimeSpan timeout, CancellationToken cancellationToken)
        {
            DataTable result = null;

            // Obtiene la tabla
            using (BlockLogModel block = Manager.SolutionManager.Logger.Default.CreateBlock(LogModel.LogType.Info, "Execute query"))
            {
                if (string.IsNullOrWhiteSpace(query))
                {
                    block.Error("The query is empty");
                }
                else
                {
                    List <ScriptSqlPartModel> scripts      = new ScriptSqlTokenizer().Parse(query, arguments.Constants);
                    SparkSqlTools             sqlTools     = new SparkSqlTools();
                    ParametersDbCollection    parametersDb = ConvertParameters(arguments.Parameters);

                    // Obtiene el datatable
                    foreach (ScriptSqlPartModel script in scripts)
                    {
                        if (script.Type == ScriptSqlPartModel.PartType.Sql)
                        {
                            string sql = sqlTools.ConvertSqlNoParameters(script.Content, parametersDb, "$").TrimIgnoreNull();

                            if (!string.IsNullOrWhiteSpace(sql))
                            {
                                // Log
                                block.Info($"Executing: {sql}");
                                // Obtiene la consulta
                                if (sql.TrimIgnoreNull().StartsWith("SELECT", StringComparison.CurrentCultureIgnoreCase))
                                {
                                    if (pageSize == 0)
                                    {
                                        result = await provider.GetDataTableAsync(sql, null, CommandType.Text, timeout, cancellationToken);
                                    }
                                    else
                                    {
                                        result = await provider.GetDataTableAsync(sql, null, CommandType.Text, actualPage, pageSize, timeout, cancellationToken);
                                    }
                                }
                                else
                                {
                                    result = await ExecuteScalarQueryAsync(provider, sql, timeout, cancellationToken);
                                }
                            }
                        }
                    }
                    // Log
                    block.Info("End query");
                }
            }
            // Devuelve la última tabla obtenida
            return(result);
        }
        /// <summary>
        ///		Ejecuta una serie de comandos
        /// </summary>
        private async Task <int> ExecuteCommandsAsync(IDbProvider provider, BlockLogModel block, List <ScriptSqlPartModel> commands, ParametersDbCollection parametersDb,
                                                      TimeSpan timeout, CancellationToken cancellationToken)
        {
            int           scriptsExecuted = 0;
            SparkSqlTools sqlTools        = new SparkSqlTools();

            // Ejecuta las consultas
            foreach (ScriptSqlPartModel command in commands)
            {
                if (!cancellationToken.IsCancellationRequested && command.Type == ScriptSqlPartModel.PartType.Sql)
                {
                    // Log
                    block.Debug($"Execute: {command.Content}");
                    // Ejecuta la cadena SQL
                    await provider.ExecuteAsync(sqlTools.ConvertSqlNoParameters(command.Content, parametersDb, "$"),
                                                null, CommandType.Text, timeout, cancellationToken);

                    // Indica que se ha ejecutado una sentencia
                    scriptsExecuted++;
                }
            }
            // Devuelve el número de comandos ejecutados
            return(scriptsExecuted);
        }