text: ﻿using RepoDb.Exceptions;
  using RepoDb.Extensions;
  using RepoDb.Interfaces;
  using RepoDb.Requests;
  using System;
  using System.Collections.Generic;
  using System.Data;
  using System.Linq.Expressions;
  using System.Threading.Tasks;
  
  namespace RepoDb
  {
      /// <summary>
      /// Contains the extension methods for <see cref="IDbConnection"/> object.
      /// </summary>
      public static partial class DbConnectionExtension
      {
          #region Count<TEntity>
  
          /// <summary>
          /// Counts the number of table data from the database.
          /// </summary>
          /// <typeparam name="TEntity">The type of the data entity object.</typeparam>
          /// <param name="connection">The connection object to be used.</param>
          /// <param name="where">The dynamic expression to be used.</param>
          /// <param name="hints">The table hints to be used. See <see cref="SqlServerTableHints"/> class.</param>
          /// <param name="commandTimeout">The command timeout in seconds to be used.</param>
          /// <param name="transaction">The transaction to be used.</param>
          /// <param name="trace">The trace object to be used.</param>
          /// <param name="statementBuilder">The statement builder object to be used.</param>
          /// <returns>An integer value that holds the number of data from the database.</returns>
          public static long Count<TEntity>(this IDbConnection connection,
              object where = null,
              string hints = null,
              int? commandTimeout = null,
              IDbTransaction transaction = null,
              ITrace trace = null,
              IStatementBuilder statementBuilder = null)
              where TEntity : class
          {
              return Count<TEntity>(connection: connection,
                  where: ToQueryGroup(where),
                  hints: hints,
                  commandTimeout: commandTimeout,
                  transaction: transaction,
                  trace: trace,
                  statementBuilder: statementBuilder);
          }
  
          /// <summary>
          /// Counts the number of table data from the database.
          /// </summary>
          /// <typeparam name="TEntity">The type of the data entity object.</typeparam>
          /// <param name="connection">The connection object to be used.</param>
          /// <param name="where">The query expression to be used.</param>
          /// <param name="hints">The table hints to be used. See <see cref="SqlServerTableHints"/> class.</param>
          /// <param name="commandTimeout">The command timeout in seconds to be used.</param>
          /// <param name="transaction">The transaction to be used.</param>
          /// <param name="trace">The trace object to be used.</param>
          /// <param name="statementBuilder">The statement builder object to be used.</param>
          /// <returns>An integer value that holds the number of data from the database.</returns>
          public static long Count<TEntity>(this IDbConnection connection,
              Expression<Func<TEntity, bool>> where = null,
              string hints = null,
              int? commandTimeout = null,
              IDbTransaction transaction = null,
              ITrace trace = null,
              IStatementBuilder statementBuilder = null)
              where TEntity : class
          {
              return Count<TEntity>(connection: connection,
                  where: ToQueryGroup(where),
                  hints: hints,
                  commandTimeout: commandTimeout,
                  transaction: transaction,
                  trace: trace,
                  statementBuilder: statementBuilder);
          }
  
          /// <summary>
          /// Counts the number of table data from the database.
          /// </summary>
          /// <typeparam name="TEntity">The type of the data entity object.</typeparam>
          /// <param name="connection">The connection object to be used.</param>
          /// <param name="where">The query expression to be used.</param>
          /// <param name="hints">The table hints to be used. See <see cref="SqlServerTableHints"/> class.</param>
          /// <param name="commandTimeout">The command timeout in seconds to be used.</param>
          /// <param name="transaction">The transaction to be used.</param>
          /// <param name="trace">The trace object to be used.</param>
          /// <param name="statementBuilder">The statement builder object to be used.</param>
          /// <returns>An integer value that holds the number of data from the database.</returns>
          public static long Count<TEntity>(this IDbConnection connection,
              QueryField where = null,
              string hints = null,
              int? commandTimeout = null,
              IDbTransaction transaction = null,
              ITrace trace = null,
              IStatementBuilder statementBuilder = null)
              where TEntity : class
          {
              return Count<TEntity>(connection: connection,
                  where: ToQueryGroup(where),
                  hints: hints,
                  commandTimeout: commandTimeout,
                  transaction: transaction,
                  trace: trace,
                  statementBuilder: statementBuilder);
          }
  
          /// <summary>
          /// Counts the number of table data from the database.
          /// </summary>
          /// <typeparam name="TEntity">The type of the data entity object.</typeparam>
          /// <param name="connection">The connection object to be used.</param>
          /// <param name="where">The query expression to be used.</param>
          /// <param name="hints">The table hints to be used. See <see cref="SqlServerTableHints"/> class.</param>
          /// <param name="commandTimeout">The command timeout in seconds to be used.</param>
          /// <param name="transaction">The transaction to be used.</param>
          /// <param name="trace">The trace object to be used.</param>
          /// <param name="statementBuilder">The statement builder object to be used.</param>
          /// <returns>An integer value that holds the number of data from the database.</returns>
          public static long Count<TEntity>(this IDbConnection connection,
              IEnumerable<QueryField> where = null,
              string hints = null,
              int? commandTimeout = null,
              IDbTransaction transaction = null,
              ITrace trace = null,
              IStatementBuilder statementBuilder = null)
              where TEntity : class
          {
              return Count<TEntity>(connection: connection,
                  where: ToQueryGroup(where),
                  hints: hints,
                  commandTimeout: commandTimeout,
                  transaction: transaction,
                  trace: trace,
                  statementBuilder: statementBuilder);
          }
  
          /// <summary>
          /// Counts the number of table data from the database.
          /// </summary>
          /// <typeparam name="TEntity">The type of the data entity object.</typeparam>
          /// <param name="connection">The connection object to be used.</param>
          /// <param name="where">The query expression to be used.</param>
          /// <param name="hints">The table hints to be used. See <see cref="SqlServerTableHints"/> class.</param>
          /// <param name="commandTimeout">The command timeout in seconds to be used.</param>
          /// <param name="transaction">The transaction to be used.</param>
          /// <param name="trace">The trace object to be used.</param>
          /// <param name="statementBuilder">The statement builder object to be used.</param>
          /// <returns>An integer value that holds the number of data from the database.</returns>
          public static long Count<TEntity>(this IDbConnection connection,
              QueryGroup where = null,
              string hints = null,
              int? commandTimeout = null,
              IDbTransaction transaction = null,
              ITrace trace = null,
              IStatementBuilder statementBuilder = null)
              where TEntity : class
          {
              return CountInternal<TEntity>(connection: connection,
                  where: where,
                  hints: hints,
                  commandTimeout: commandTimeout,
                  transaction: transaction,
                  trace: trace,
                  statementBuilder: statementBuilder);
          }
  
          /// <summary>
          /// Counts the number of table data from the database.
          /// </summary>
          /// <typeparam name="TEntity">The type of the data entity object.</typeparam>
          /// <param name="connection">The connection object to be used.</param>
          /// <param name="where">The query expression to be used.</param>
          /// <param name="hints">The table hints to be used. See <see cref="SqlServerTableHints"/> class.</param>
          /// <param name="commandTimeout">The command timeout in seconds to be used.</param>
          /// <param name="transaction">The transaction to be used.</param>
          /// <param name="trace">The trace object to be used.</param>
          /// <param name="statementBuilder">The statement builder object to be used.</param>
          /// <returns>An integer value that holds the number of data from the database.</returns>
          internal static long CountInternal<TEntity>(this IDbConnection connection,
              QueryGroup where = null,
              string hints = null,
              int? commandTimeout = null,
              IDbTransaction transaction = null,
              ITrace trace = null,
              IStatementBuilder statementBuilder = null)
              where TEntity : class
          {
              // Variables
              var request = new CountRequest(typeof(TEntity),
                  connection,
                  transaction,
                  where,
                  hints,
                  statementBuilder);
              var param = (object)null;
  
              // Converts to propery mapped object
              if (where != null)
              {
                  param = QueryGroup.AsMappedObject(new[] { where.MapTo<TEntity>() });
              }
  
              // Return the result
              return CountInternalBase(connection: connection,
                  request: request,
                  param: param,
                  commandTimeout: commandTimeout,
                  transaction: transaction,
                  trace: trace);
          }
  
          #endregion
  
          #region CountAsync<TEntity>
  
          /// <summary>
          /// Counts the number of table data from the database in an asynchronous way.
          /// </summary>
          /// <typeparam name="TEntity">The type of the data entity object.</typeparam>
          /// <param name="connection">The connection object to be used.</param>
          /// <param name="where">The dynamic expression to be used.</param>
          /// <param name="hints">The table hints to be used. See <see cref="SqlServerTableHints"/> class.</param>
          /// <param name="commandTimeout">The command timeout in seconds to be used.</param>
          /// <param name="transaction">The transaction to be used.</param>
          /// <param name="trace">The trace object to be used.</param>
          /// <param name="statementBuilder">The statement builder object to be used.</param>
          /// <returns>An integer value that holds the number of data from the database.</returns>
          public static Task<long> CountAsync<TEntity>(this IDbConnection connection,
              object where = null,
              string hints = null,
              int? commandTimeout = null,
              IDbTransaction transaction = null,
              ITrace trace = null,
              IStatementBuilder statementBuilder = null)
              where TEntity : class
          {
              return CountAsync<TEntity>(connection: connection,
                  where: ToQueryGroup(where),
                  hints: hints,
                  commandTimeout: commandTimeout,
                  transaction: transaction,
                  trace: trace,
                  statementBuilder: statementBuilder);
          }
  
          /// <summary>
          /// Counts the number of table data from the database in an asynchronous way.
          /// </summary>
          /// <typeparam name="TEntity">The type of the data entity object.</typeparam>
          /// <param name="connection">The connection object to be used.</param>
          /// <param name="where">The query expression to be used.</param>
          /// <param name="hints">The table hints to be used. See <see cref="SqlServerTableHints"/> class.</param>
          /// <param name="commandTimeout">The command timeout in seconds to be used.</param>
          /// <param name="transaction">The transaction to be used.</param>
          /// <param name="trace">The trace object to be used.</param>
          /// <param name="statementBuilder">The statement builder object to be used.</param>
          /// <returns>An integer value that holds the number of data from the database.</returns>
          public static Task<long> CountAsync<TEntity>(this IDbConnection connection,
              Expression<Func<TEntity, bool>> where = null,
              string hints = null,
              int? commandTimeout = null,
              IDbTransaction transaction = null,
              ITrace trace = null,
              IStatementBuilder statementBuilder = null)
              where TEntity : class
          {
              return CountAsync<TEntity>(connection: connection,
                  where: ToQueryGroup(where),
                  hints: hints,
                  commandTimeout: commandTimeout,
                  transaction: transaction,
                  trace: trace,
                  statementBuilder: statementBuilder);
          }
  
          /// <summary>
          /// Counts the number of table data from the database in an asynchronous way.
          /// </summary>
          /// <typeparam name="TEntity">The type of the data entity object.</typeparam>
          /// <param name="connection">The connection object to be used.</param>
          /// <param name="where">The query expression to be used.</param>
          /// <param name="hints">The table hints to be used. See <see cref="SqlServerTableHints"/> class.</param>
          /// <param name="commandTimeout">The command timeout in seconds to be used.</param>
          /// <param name="transaction">The transaction to be used.</param>
          /// <param name="trace">The trace object to be used.</param>
          /// <param name="statementBuilder">The statement builder object to be used.</param>
          /// <returns>An integer value that holds the number of data from the database.</returns>
          public static Task<long> CountAsync<TEntity>(this IDbConnection connection,
              QueryField where = null,
              string hints = null,
              int? commandTimeout = null,
              IDbTransaction transaction = null,
              ITrace trace = null,
              IStatementBuilder statementBuilder = null)
              where TEntity : class
          {
              return CountAsync<TEntity>(connection: connection,
                  where: ToQueryGroup(where),
                  hints: hints,
                  commandTimeout: commandTimeout,
                  transaction: transaction,
                  trace: trace,
                  statementBuilder: statementBuilder);
          }
  
          /// <summary>
          /// Counts the number of table data from the database in an asynchronous way.
          /// </summary>
          /// <typeparam name="TEntity">The type of the data entity object.</typeparam>
          /// <param name="connection">The connection object to be used.</param>
          /// <param name="where">The query expression to be used.</param>
          /// <param name="hints">The table hints to be used. See <see cref="SqlServerTableHints"/> class.</param>
          /// <param name="commandTimeout">The command timeout in seconds to be used.</param>
          /// <param name="transaction">The transaction to be used.</param>
          /// <param name="trace">The trace object to be used.</param>
          /// <param name="statementBuilder">The statement builder object to be used.</param>
          /// <returns>An integer value that holds the number of data from the database.</returns>
          public static Task<long> CountAsync<TEntity>(this IDbConnection connection,
              IEnumerable<QueryField> where = null,
              string hints = null,
              int? commandTimeout = null,
              IDbTransaction transaction = null,
              ITrace trace = null,
              IStatementBuilder statementBuilder = null)
              where TEntity : class
          {
              return CountAsync<TEntity>(connection: connection,
                  where: ToQueryGroup(where),
                  hints: hints,
                  commandTimeout: commandTimeout,
                  transaction: transaction,
                  trace: trace,
                  statementBuilder: statementBuilder);
          }
  
          /// <summary>
          /// Counts the number of table data from the database in an asynchronous way.
          /// </summary>
          /// <typeparam name="TEntity">The type of the data entity object.</typeparam>
          /// <param name="connection">The connection object to be used.</param>
          /// <param name="where">The query expression to be used.</param>
          /// <param name="hints">The table hints to be used. See <see cref="SqlServerTableHints"/> class.</param>
          /// <param name="commandTimeout">The command timeout in seconds to be used.</param>
          /// <param name="transaction">The transaction to be used.</param>
          /// <param name="trace">The trace object to be used.</param>
          /// <param name="statementBuilder">The statement builder object to be used.</param>
          /// <returns>An integer value that holds the number of data from the database.</returns>
          public static Task<long> CountAsync<TEntity>(this IDbConnection connection,
              QueryGroup where = null,
              string hints = null,
              int? commandTimeout = null,
              IDbTransaction transaction = null,
              ITrace trace = null,
              IStatementBuilder statementBuilder = null)
              where TEntity : class
          {
              return CountAsyncInternal<TEntity>(connection: connection,
                  where: where,
                  hints: hints,
                  commandTimeout: commandTimeout,
                  transaction: transaction,
                  trace: trace,
                  statementBuilder: statementBuilder);
          }
  
          /// <summary>
          /// Counts the number of table data from the database in an asynchronous way.
          /// </summary>
          /// <typeparam name="TEntity">The type of the data entity object.</typeparam>
          /// <param name="connection">The connection object to be used.</param>
          /// <param name="where">The query expression to be used.</param>
          /// <param name="hints">The table hints to be used. See <see cref="SqlServerTableHints"/> class.</param>
          /// <param name="commandTimeout">The command timeout in seconds to be used.</param>
          /// <param name="transaction">The transaction to be used.</param>
          /// <param name="trace">The trace object to be used.</param>
          /// <param name="statementBuilder">The statement builder object to be used.</param>
          /// <returns>An integer value that holds the number of data from the database.</returns>
          internal static Task<long> CountAsyncInternal<TEntity>(this IDbConnection connection,
              QueryGroup where = null,
              int? commandTimeout = null,
              string hints = null,
              IDbTransaction transaction = null,
              ITrace trace = null,
              IStatementBuilder statementBuilder = null)
              where TEntity : class
          {
              // Variables
              var request = new CountRequest(typeof(TEntity),
                  connection,
                  transaction,
                  where,
                  hints,
                  statementBuilder);
              var param = (object)null;
  
              // Converts to propery mapped object
              if (where != null)
              {
                  param = QueryGroup.AsMappedObject(new[] { where.MapTo<TEntity>() });
              }
  
              // Return the result
              return CountInternalAsyncBase(connection: connection,
                  request: request,
                  param: param,
                  commandTimeout: commandTimeout,
                  transaction: transaction,
                  trace: trace);
          }
  
          #endregion
  
          #region Count(TableName)
  
          /// <summary>
          /// Counts the number of table data from the database.
          /// </summary>
          /// <param name="connection">The connection object to be used.</param>
          /// <param name="tableName">The name of the target table to be used.</param>
          /// <param name="where">The dynamic expression to be used.</param>
          /// <param name="hints">The table hints to be used. See <see cref="SqlServerTableHints"/> class.</param>
          /// <param name="commandTimeout">The command timeout in seconds to be used.</param>
          /// <param name="transaction">The transaction to be used.</param>
          /// <param name="trace">The trace object to be used.</param>
          /// <param name="statementBuilder">The statement builder object to be used.</param>
          /// <returns>An integer value that holds the number of data from the database.</returns>
          public static long Count(this IDbConnection connection,
              string tableName,
              object where = null,
              string hints = null,
              int? commandTimeout = null,
              IDbTransaction transaction = null,
              ITrace trace = null,
              IStatementBuilder statementBuilder = null)
          {
              return Count(connection: connection,
                  tableName: tableName,
                  where: ToQueryGroup(where),
                  hints: hints,
                  commandTimeout: commandTimeout,
                  transaction: transaction,
                  trace: trace,
                  statementBuilder: statementBuilder);
          }
  
          /// <summary>
          /// Counts the number of table data from the database.
          /// </summary>
          /// <param name="connection">The connection object to be used.</param>
          /// <param name="tableName">The name of the target table to be used.</param>
          /// <param name="where">The query expression to be used.</param>
          /// <param name="hints">The table hints to be used. See <see cref="SqlServerTableHints"/> class.</param>
          /// <param name="commandTimeout">The command timeout in seconds to be used.</param>
          /// <param name="transaction">The transaction to be used.</param>
          /// <param name="trace">The trace object to be used.</param>
          /// <param name="statementBuilder">The statement builder object to be used.</param>
          /// <returns>An integer value that holds the number of data from the database.</returns>
          public static long Count(this IDbConnection connection,
              string tableName,
              QueryField where = null,
              string hints = null,
              int? commandTimeout = null,
              IDbTransaction transaction = null,
              ITrace trace = null,
              IStatementBuilder statementBuilder = null)
          {
              return Count(connection: connection,
                  tableName: tableName,
                  where: ToQueryGroup(where),
                  hints: hints,
                  commandTimeout: commandTimeout,
                  transaction: transaction,
                  trace: trace,
                  statementBuilder: statementBuilder);
          }
  
          /// <summary>
          /// Counts the number of table data from the database.
          /// </summary>
          /// <param name="connection">The connection object to be used.</param>
          /// <param name="tableName">The name of the target table to be used.</param>
          /// <param name="where">The query expression to be used.</param>
          /// <param name="hints">The table hints to be used. See <see cref="SqlServerTableHints"/> class.</param>
          /// <param name="commandTimeout">The command timeout in seconds to be used.</param>
          /// <param name="transaction">The transaction to be used.</param>
          /// <param name="trace">The trace object to be used.</param>
          /// <param name="statementBuilder">The statement builder object to be used.</param>
          /// <returns>An integer value that holds the number of data from the database.</returns>
          public static long Count(this IDbConnection connection,
              string tableName,
              IEnumerable<QueryField> where = null,
              string hints = null,
              int? commandTimeout = null,
              IDbTransaction transaction = null,
              ITrace trace = null,
              IStatementBuilder statementBuilder = null)
          {
              return Count(connection: connection,
                  tableName: tableName,
                  where: ToQueryGroup(where),
                  hints: hints,
                  commandTimeout: commandTimeout,
                  transaction: transaction,
                  trace: trace,
                  statementBuilder: statementBuilder);
          }
  
          /// <summary>
          /// Counts the number of table data from the database.
          /// </summary>
          /// <param name="connection">The connection object to be used.</param>
          /// <param name="tableName">The name of the target table to be used.</param>
          /// <param name="where">The query expression to be used.</param>
          /// <param name="hints">The table hints to be used. See <see cref="SqlServerTableHints"/> class.</param>
          /// <param name="commandTimeout">The command timeout in seconds to be used.</param>
          /// <param name="transaction">The transaction to be used.</param>
          /// <param name="trace">The trace object to be used.</param>
          /// <param name="statementBuilder">The statement builder object to be used.</param>
          /// <returns>An integer value that holds the number of data from the database.</returns>
          public static long Count(this IDbConnection connection,
              string tableName,
              QueryGroup where = null,
              string hints = null,
              int? commandTimeout = null,
              IDbTransaction transaction = null,
              ITrace trace = null,
              IStatementBuilder statementBuilder = null)
          {
              return CountInternal(connection: connection,
                  tableName: tableName,
                  where: where,
                  hints: hints,
                  commandTimeout: commandTimeout,
                  transaction: transaction,
                  trace: trace,
                  statementBuilder: statementBuilder);
          }
  
          /// <summary>
          /// Counts the number of table data from the database.
          /// </summary>
          /// <param name="connection">The connection object to be used.</param>
          /// <param name="tableName">The name of the target table to be used.</param>
          /// <param name="where">The query expression to be used.</param>
          /// <param name="hints">The table hints to be used. See <see cref="SqlServerTableHints"/> class.</param>
          /// <param name="commandTimeout">The command timeout in seconds to be used.</param>
          /// <param name="transaction">The transaction to be used.</param>
          /// <param name="trace">The trace object to be used.</param>
          /// <param name="statementBuilder">The statement builder object to be used.</param>
          /// <returns>An integer value that holds the number of data from the database.</returns>
          internal static long CountInternal(this IDbConnection connection,
              string tableName,
              QueryGroup where = null,
              string hints = null,
              int? commandTimeout = null,
              IDbTransaction transaction = null,
              ITrace trace = null,
              IStatementBuilder statementBuilder = null)
          {
              // Variables
              var request = new CountRequest(tableName,
                  connection,
                  transaction,
                  where,
                  hints,
                  statementBuilder);
              var param = (object)null;
  
              // Converts to propery mapped object
              if (where != null)
              {
                  param = QueryGroup.AsMappedObject(new[] { where.MapTo(null) });
              }
  
              // Return the result
              return CountInternalBase(connection: connection,
                  request: request,
                  param: param,
                  commandTimeout: commandTimeout,
                  transaction: transaction,
                  trace: trace);
          }
  
          #endregion
  
          #region CountAsync(TableName)
  
          /// <summary>
          /// Counts the number of table data from the database in an asynchronous way.
          /// </summary>
          /// <param name="connection">The connection object to be used.</param>
          /// <param name="tableName">The name of the target table to be used.</param>
          /// <param name="where">The dynamic expression to be used.</param>
          /// <param name="hints">The table hints to be used. See <see cref="SqlServerTableHints"/> class.</param>
          /// <param name="commandTimeout">The command timeout in seconds to be used.</param>
          /// <param name="transaction">The transaction to be used.</param>
          /// <param name="trace">The trace object to be used.</param>
          /// <param name="statementBuilder">The statement builder object to be used.</param>
          /// <returns>An integer value that holds the number of data from the database.</returns>
          public static Task<long> CountAsync(this IDbConnection connection,
              string tableName,
              object where = null,
              string hints = null,
              int? commandTimeout = null,
              IDbTransaction transaction = null,
              ITrace trace = null,
              IStatementBuilder statementBuilder = null)
          {
              return CountAsync(connection: connection,
                  tableName: tableName,
                  where: ToQueryGroup(where),
                  hints: hints,
                  commandTimeout: commandTimeout,
                  transaction: transaction,
                  trace: trace,
                  statementBuilder: statementBuilder);
          }
  
          /// <summary>
          /// Counts the number of table data from the database in an asynchronous way.
          /// </summary>
          /// <param name="connection">The connection object to be used.</param>
          /// <param name="tableName">The name of the target table to be used.</param>
          /// <param name="where">The query expression to be used.</param>
          /// <param name="hints">The table hints to be used. See <see cref="SqlServerTableHints"/> class.</param>
          /// <param name="commandTimeout">The command timeout in seconds to be used.</param>
          /// <param name="transaction">The transaction to be used.</param>
          /// <param name="trace">The trace object to be used.</param>
          /// <param name="statementBuilder">The statement builder object to be used.</param>
          /// <returns>An integer value that holds the number of data from the database.</returns>
          public static Task<long> CountAsync(this IDbConnection connection,
              string tableName,
              QueryField where = null,
              string hints = null,
              int? commandTimeout = null,
              IDbTransaction transaction = null,
              ITrace trace = null,
              IStatementBuilder statementBuilder = null)
          {
              return CountAsync(connection: connection,
                  tableName: tableName,
                  where: ToQueryGroup(where),
                  hints: hints,
                  commandTimeout: commandTimeout,
                  transaction: transaction,
                  trace: trace,
                  statementBuilder: statementBuilder);
          }
  
          /// <summary>
          /// Counts the number of table data from the database in an asynchronous way.
          /// </summary>
          /// <param name="connection">The connection object to be used.</param>
          /// <param name="tableName">The name of the target table to be used.</param>
          /// <param name="where">The query expression to be used.</param>
          /// <param name="hints">The table hints to be used. See <see cref="SqlServerTableHints"/> class.</param>
          /// <param name="commandTimeout">The command timeout in seconds to be used.</param>
          /// <param name="transaction">The transaction to be used.</param>
          /// <param name="trace">The trace object to be used.</param>
          /// <param name="statementBuilder">The statement builder object to be used.</param>
          /// <returns>An integer value that holds the number of data from the database.</returns>
          public static Task<long> CountAsync(this IDbConnection connection,
              string tableName,
              IEnumerable<QueryField> where = null,
              string hints = null,
              int? commandTimeout = null,
              IDbTransaction transaction = null,
              ITrace trace = null,
              IStatementBuilder statementBuilder = null)
          {
              return CountAsync(connection: connection,
                  tableName: tableName,
                  where: ToQueryGroup(where),
                  hints: hints,
                  commandTimeout: commandTimeout,
                  transaction: transaction,
                  trace: trace,
                  statementBuilder: statementBuilder);
          }
  
          /// <summary>
          /// Counts the number of table data from the database in an asynchronous way.
          /// </summary>
          /// <param name="connection">The connection object to be used.</param>
          /// <param name="tableName">The name of the target table to be used.</param>
          /// <param name="where">The query expression to be used.</param>
          /// <param name="hints">The table hints to be used. See <see cref="SqlServerTableHints"/> class.</param>
          /// <param name="commandTimeout">The command timeout in seconds to be used.</param>
          /// <param name="transaction">The transaction to be used.</param>
          /// <param name="trace">The trace object to be used.</param>
          /// <param name="statementBuilder">The statement builder object to be used.</param>
          /// <returns>An integer value that holds the number of data from the database.</returns>
          public static Task<long> CountAsync(this IDbConnection connection,
              string tableName,
              QueryGroup where = null,
              string hints = null,
              int? commandTimeout = null,
              IDbTransaction transaction = null,
              ITrace trace = null,
              IStatementBuilder statementBuilder = null)
          {
              return CountAsyncInternal(connection: connection,
                  tableName: tableName,
                  where: where,
                  hints: hints,
                  commandTimeout: commandTimeout,
                  transaction: transaction,
                  trace: trace,
                  statementBuilder: statementBuilder);
          }
  
          /// <summary>
          /// Counts the number of table data from the database in an asynchronous way.
          /// </summary>
          /// <param name="connection">The connection object to be used.</param>
          /// <param name="tableName">The name of the target table to be used.</param>
          /// <param name="where">The query expression to be used.</param>
          /// <param name="hints">The table hints to be used. See <see cref="SqlServerTableHints"/> class.</param>
          /// <param name="commandTimeout">The command timeout in seconds to be used.</param>
          /// <param name="transaction">The transaction to be used.</param>
          /// <param name="trace">The trace object to be used.</param>
          /// <param name="statementBuilder">The statement builder object to be used.</param>
          /// <returns>An integer value that holds the number of data from the database.</returns>
          internal static Task<long> CountAsyncInternal(this IDbConnection connection,
              string tableName,
              QueryGroup where = null,
              string hints = null,
              int? commandTimeout = null,
              IDbTransaction transaction = null,
              ITrace trace = null,
              IStatementBuilder statementBuilder = null)
          {
              // Variables
              var request = new CountRequest(tableName,
                  connection,
                  transaction,
                  where,
                  hints,
                  statementBuilder);
              var param = (object)null;
  
              // Converts to propery mapped object
              if (where != null)
              {
                  param = QueryGroup.AsMappedObject(new[] { where.MapTo(null) });
              }
  
              // Return the result
              return CountInternalAsyncBase(connection: connection,
                  request: request,
                  param: param,
                  commandTimeout: commandTimeout,
                  transaction: transaction,
                  trace: trace);
          }
  
          #endregion
  
          #region CounterInternalBase
  
          /// <summary>
          /// Counts the number of table data from the database.
          /// </summary>
          /// <param name="connection">The connection object to be used.</param>
          /// <param name="request">The actual <see cref="CountRequest"/> object.</param>
          /// <param name="param">The mapped object parameters.</param>
          /// <param name="commandTimeout">The command timeout in seconds to be used.</param>
          /// <param name="transaction">The transaction to be used.</param>
          /// <param name="trace">The trace object to be used.</param>
          /// <returns>An integer value that holds the number of data from the database.</returns>
          internal static long CountInternalBase(this IDbConnection connection,
              CountRequest request,
              object param,
              int? commandTimeout = null,
              IDbTransaction transaction = null,
              ITrace trace = null)
          {
              // Variables
              var commandType = CommandType.Text;
              var commandText = CommandTextCache.GetCountText(request);
  
              // Before Execution
              if (trace != null)
              {
                  var cancellableTraceLog = new CancellableTraceLog(commandText, param, null);
                  trace.BeforeCount(cancellableTraceLog);
                  if (cancellableTraceLog.IsCancelled)
                  {
                      if (cancellableTraceLog.IsThrowException)
                      {
                          throw new CancelledExecutionException(commandText);
                      }
                      return default(int);
                  }
                  commandText = (cancellableTraceLog.Statement ?? commandText);
                  param = (cancellableTraceLog.Parameter ?? param);
              }
  
              // Before Execution Time
              var beforeExecutionTime = DateTime.UtcNow;
  
              // Actual Execution
              var result = ExecuteScalarInternal<long>(connection: connection,
                  commandText: commandText,
                  param: param,
                  commandType: commandType,
                  commandTimeout: commandTimeout,
                  transaction: transaction,
                  skipCommandArrayParametersCheck: true);
  
              // After Execution
              if (trace != null)
              {
                  trace.AfterCount(new TraceLog(commandText, param, result,
                      DateTime.UtcNow.Subtract(beforeExecutionTime)));
              }
  
              // Result
              return result;
          }
  
          #endregion
  
          #region CountAsyncInternalBase
  
          /// <summary>
          /// Counts the number of table data from the database in an asynchronous way.
          /// </summary>
          /// <param name="connection">The connection object to be used.</param>
          /// <param name="request">The actual <see cref="CountRequest"/> object.</param>
          /// <param name="param">The mapped object parameters.</param>
          /// <param name="commandTimeout">The command timeout in seconds to be used.</param>
          /// <param name="transaction">The transaction to be used.</param>
          /// <param name="trace">The trace object to be used.</param>
          /// <returns>An integer value that holds the number of data from the database.</returns>
          internal static async Task<long> CountInternalAsyncBase(this IDbConnection connection,
              CountRequest request,
              object param,
              int? commandTimeout = null,
              IDbTransaction transaction = null,
              ITrace trace = null)
          {
              // Variables
              var commandType = CommandType.Text;
              var commandText = CommandTextCache.GetCountText(request);
  
              // Before Execution
              if (trace != null)
              {
                  var cancellableTraceLog = new CancellableTraceLog(commandText, param, null);
                  trace.BeforeCount(cancellableTraceLog);
                  if (cancellableTraceLog.IsCancelled)
                  {
                      if (cancellableTraceLog.IsThrowException)
                      {
                          throw new CancelledExecutionException(commandText);
                      }
                      return default(int);
                  }
                  commandText = (cancellableTraceLog.Statement ?? commandText);
                  param = (cancellableTraceLog.Parameter ?? param);
              }
  
              // Before Execution Time
              var beforeExecutionTime = DateTime.UtcNow;
  
              // Actual Execution
              var result = await ExecuteScalarAsyncInternal<long>(connection: connection,
                  commandText: commandText,
                  param: param,
                  commandType: commandType,
                  commandTimeout: commandTimeout,
                  transaction: transaction,
                  skipCommandArrayParametersCheck: true);
  
              // After Execution
              if (trace != null)
              {
                  trace.AfterCount(new TraceLog(commandText, param, result,
                      DateTime.UtcNow.Subtract(beforeExecutionTime)));
              }
  
              // Result
              return result;
          }
  
          #endregion
      }
  }
  