/*
 * 作者:吴隆健
 * 日期: 2019-04-23
 * 时间: 13:17
 * 
 */

using System;
using System.Data;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Threading.Tasks;

namespace MrWu.DB {
    /// <summary>
    /// sql链接  T是sql的链接类型 K是指令类型  M是参数类型
    /// </summary>
    public interface ISqlEx<T,K,M,N> {
        /// <summary>
        /// 链接池
        /// </summary>
        IConnectionPool<T> connPool {
            get;
        }

        /// <summary>
        /// 获取一个连接
        /// </summary>
        /// <param name="dbbase"></param>
        /// <returns></returns>
        T GetConnection(string dbbase);

        /// <summary>
        /// 开始执行存储过程
        /// </summary>
        /// <param name="dbbase">数据库名称</param>
        /// <param name="procedure">存储过程名称</param>
        /// <returns></returns>
        IProdureParameter<K> BeginProcedure(string dbbase,string procedure);

        /// <summary>
        /// 给存储过程添加参数
        /// </summary>
        /// <param name="spp">存储过程命令</param>
        /// <param name="paramName">参数名</param>
        /// <param name="value">参数值</param>
        /// <param name="type">参数类型</param>
        /// <param name="pd">参数种类</param>
        void AddParam(IProdureParameter<K> spp,string paramName,object value,M type,ParameterDirection pd = ParameterDirection.Input);

        /// <summary>
        /// 提交存储过程
        /// </summary>
        /// <param name="spp">存储过程命令</param>
        /// <param name="ds">查询的结果集</param>
        /// <param name="againCount">重试次数 小于0表示使用配置值 大于等于0表示自定义</param>
        /// <returns>执行存储过程所有参数</returns>
        Dictionary<string, object> SubProcedure(IProdureParameter<K> spp, DataSet ds = null,int againCount = -1);

        /// <summary>
        /// 执行sql语句
        /// </summary>
        /// <param name="dbbase">数据库名称</param>
        /// <param name="sql">sql语句</param>
        /// <param name="sqlparams">sql的额外参数</param>
        /// <param name="ds">查询的结果集</param>
        /// <param name="againCount">重试次数 小于0表示使用配置值 大于等于0表示自定义</param>
        /// <returns>受影响的行数</returns>
        int ExecuteSql(string dbbase,string sql,IEnumerable<N> sqlparams = null,DataSet ds = null,int againCount = -1);

        /// <summary>
        /// 执行一个普通的查询
        /// </summary>
        /// <param name="dbbase">数据库名称</param>
        /// <param name="table">数据库表名</param>
        /// <param name="column">查询的列</param>
        /// <param name="where">查询条件</param>
        /// <param name="count">查询的行数</param>
        /// <param name="againCount">重试次数 小于0表示使用配置值 大于等于0表示自定义</param>
        /// <param name="sqlparams">sql参数</param>
        /// <returns>查询的结果集</returns>
        DataTable Select(string dbbase, string table, string[] column = null, string where = null, int count = 0,int againCount = -1, IEnumerable<N> sqlparams = null);

        /// <summary>
        /// 执行cmd
        /// </summary>
        /// <param name="cmd">数据库指令</param>
        /// <param name="dbname">数据库名称</param>
        /// <param name="ds">结果集</param>
        /// <param name="againCount">重试次数 小于0表示使用配置值 大于等于0表示自定义</param>
        /// <returns>受影响的行数</returns>
        int Execute(K cmd,string dbname, DataSet ds = null,int againCount = -1);

        /// <summary>
        /// 执行一个事务
        /// </summary>
        /// <param name="dbbase">数据库名称</param>
        /// <returns>存储过程指令</returns>
        IProdureParameter<K> BeginTransaction(string dbbase);

        /// <summary>
        /// 为事务添加sql语句
        /// </summary>
        /// <param name="spp">存储过程指令</param>
        /// <param name="sql">sql语句</param>
        /// <param name="sqlparams">额外参数</param>
        int TransactionAddSql(IProdureParameter<K> spp, string sql, List<ISqlAloneParameter<M>> sqlparams = null);

        /// <summary>
        /// 提交一个事务
        /// </summary>
        /// <param name="spp">存储过程指令</param>
        /// <returns></returns>
        bool SubTransaction(IProdureParameter<K> spp);

        /// <summary>
        /// 回滚事务
        /// </summary>
        /// <param name="spp"></param>
        void RollbackTransaction(IProdureParameter<K> spp);

        #region 异步方法

        /// <summary>
        /// 异步提交存储过程
        /// </summary>
        /// <param name="spp">存储过程命令</param>
        /// <param name="ds">查询的结果集</param>
        /// <param name="againCount">重试次数 小于0表示使用配置值 大于等于0表示自定义</param>
        /// <returns>执行存储过程所有参数</returns>
        Task<Dictionary<string, object>> SubProcedureAsync(IProdureParameter<K> spp, DataSet ds = null, int againCount = -1);

        /// <summary>
        /// 异步执行sql语句
        /// </summary>
        /// <param name="dbbase">数据库名称</param>
        /// <param name="sql">sql语句</param>
        /// <param name="sqlparams">sql的额外参数</param>
        /// <param name="ds">查询的结果集</param>
        /// <param name="againCount">重试次数 小于0表示使用配置值 大于等于0表示自定义</param>
        /// <returns>受影响的行数</returns>
        Task<int> ExecuteSqlAsync(string dbbase, string sql, IEnumerable<N> sqlparams = null, DataSet ds = null, int againCount = -1);

        /// <summary>
        /// 异步执行一个普通的查询
        /// </summary>
        /// <param name="dbbase">数据库名称</param>
        /// <param name="table">数据库表名</param>
        /// <param name="column">查询的列</param>
        /// <param name="where">查询条件</param>
        /// <param name="count">查询的行数</param>
        /// <param name="againCount">重试次数 小于0表示使用配置值 大于等于0表示自定义</param>
        /// <param name="sqlparams">sql参数</param>
        /// <returns>查询的结果集</returns>
        Task<DataTable> SelectAsync(string dbbase, string table, string[] column = null, string where = null, int count = 0, int againCount = -1, IEnumerable<N> sqlparams = null);

        /// <summary>
        /// 异步执行cmd
        /// </summary>
        /// <param name="cmd">数据库指令</param>
        /// <param name="dbname">数据库名称</param>
        /// <param name="ds">结果集</param>
        /// <param name="againCount">重试次数 小于0表示使用配置值 大于等于0表示自定义</param>
        /// <returns>受影响的行数</returns>
        Task<int> ExecuteAsync(K cmd, string dbname, DataSet ds = null, int againCount = -1);

        #endregion
    }
}
