• 一、打造DataProvider


    一、打造DataProvider

    ADO.Net的封装已经有很多的实现了,但我总感觉那些实现还是没有透明化使用者对ADO.Net的了解。比如说很多人推崇的Enterprise LibraryDataAccess,我认为就是封装不够彻底。我理想中封装彻底的ADO.Net对象是,使用者不需要(或尽可能的少)了解任何,而DataAccess还是需要使用者直接的处理很多ADO.Net的对象。而我需要的ADO.Net的封装希望使用者,仅给予SQL命令,赋值参数,并获取结果即可。

    1.1定义DataProvide

    定义SqlDataProvider

    /// <summary>

    /// SQL数据提供者的实现

    /// </summary>

    public class SqlDataProvider : DataProviders.IDataProvider

    {

     

    }

    1.2定义DataProviders.IDataProvider

    DataProviders.IDataProvider是我定义的一个接口,我希望将来所有的数据提供者都能实现该接口,以便利用依赖倒置实现抽象工厂。

    定义DataProviders.IDataProvider接口

    public interface IDataProvider

    {

        void AddParameters(string parname, Guid value);

        void AddParameters(string parname, long value);

        void AddParameters(string parname, string value);

        void AddParameters(string parname, string value, DataProviders.StringFamily dataType);

        void AddParameters(string parname, string value, DataProviders.StringFamily dataType, int size);

        void AddParameters(string parname, float value);

        void AddParameters(string parname, decimal value);

        void AddParameters(string parname, DateTime value);

        void AddParameters(string parname, DateTime value, DataProviders.DateFamily dataType);

        void AddParameters(string parname, int value);

        void AddParameters(string parname, object value);

        void AddParameters(string parname, System.Drawing.Bitmap value);

        void AddParameters(string parname, byte[] value);

        void AddParameters(string parname, byte[] value, DataProviders.ByteArrayFamily dataType);

        void AddParameters(string parname, bool value);

        void AddParameters(string parname, short value);

        void AddParameters(string parname, byte value);

        System.Data.CommandType CommandType { get; set; }

        string ConnectionString { get; }

        System.Data.DataSet ExecuteDataSet();

        System.Data.DataTable ExecuteDataTable();

        void ExecuteReader(ReadData readData);

        int ExecuteNonQuery();

        object ExecuteScalar();

        string SQL { get; set; }

    }

     

    public delegate void ReadData(System.Data.IDataReader dataReadre);

    从该接口可以看到,实现的DataProvider封装了关于具体的连接对象,命令对象和参数类型的信息。

    1.3实现DataProvider基础部分

    SqlDataProvider类实现(基础部分)

    private static System.Data.SqlClient.SqlConnection conn;

    private System.Data.SqlClient.SqlCommand cmd;

     

    /// <summary>

    /// 默认构造函数

    /// </summary>

    public SqlDataProvider()

    {

     

    }

     

    /// <summary>

    /// 接受连接字符串

    /// </summary>

    /// <param name="connstr"></param>

    public SqlDataProvider(string connstr)

        : this(connstr, "")

    {

     

    }

     

    /// <summary>

    /// 接受连接字符串和sql字符串

    /// </summary>

    /// <param name="connstr"></param>

    /// <param name="sql"></param>

    public SqlDataProvider(string connstr, string sql)

    {

        conn = new System.Data.SqlClient.SqlConnection(connstr);

        cmd = new System.Data.SqlClient.SqlCommand();

        cmd.Connection = conn;

        cmd.CommandText = sql;

    }

     

    /// <summary>

    /// 需要执行的SQL命令

    /// </summary>

    public string SQL

    {

        set

        {

            cmd.CommandText = value;

        }

        get

        {

            return cmd.CommandText;

        }

    }

     

    /// <summary>

    /// 当前的连接字符串

    /// </summary>

    public string ConnectionString

    {

        get

        {

            return conn.ConnectionString;

        }

    }

     

    /// <summary>

    /// 设置命令的类型

    /// </summary>

    public System.Data.CommandType CommandType

    {

        set

        {

            cmd.CommandType = value;

        }

        get

        {

            return cmd.CommandType;

        }

    }

    从上述代码可以观察到,我们的DataProvider只向用户暴露了两个字符串数据:连接字符串和SQL指令字符串。而将ADO.Net特有的ConnectionCommand封装起来了。由于用户不需要了解到具体实例化的ConnectionCommand,则为以后对其他数据源提供者的扩展带来了机会。

    1.4实现DataProvider数据执行部分

    SqlDataProvider类实现(数据执行部分)

    /// <summary>

    /// 将SqlDataReader提交给具体的委托器处理

    /// </summary>

    /// <param name="readData"></param>

    public void ExecuteReader(ReadData readData)

    {

        using (conn)

        {

            conn.Open();

            System.Data.SqlClient.SqlDataReader dr = cmd.ExecuteReader();

            readData(dr);

            conn.Close();

        }

    }

     

    /// <summary>

    /// 对连接执行 Transact-SQL 语句并返回受影响的行数

    /// </summary>

    /// <returns></returns>

    public int ExecuteNonQuery()

    {

        int result = -1;

        using (conn)

        {

            conn.Open();

            result = cmd.ExecuteNonQuery();

            conn.Close();

        }

        return result;

    }

     

    /// <summary>

    /// 执行查询,并返回查询所返回的结果集中第一行的第一列。忽略其他列或行

    /// </summary>

    /// <returns></returns>

    public object ExecuteScalar()

    {

        object result = null;

        using (conn)

        {

            conn.Open();

            result = cmd.ExecuteScalar();

            conn.Close();

        }

        return result;

    }

     

     

    /// <summary>

    /// 执行查询,并返回查询的DataSet

    /// </summary>

    /// <returns></returns>

    public System.Data.DataSet ExecuteDataSet()

    {

        System.Data.DataSet datadet = new System.Data.DataSet();

        using (conn)

        {

            System.Data.SqlClient.SqlDataAdapter adapter = new System.Data.SqlClient.SqlDataAdapter();

            adapter.SelectCommand = cmd;

            conn.Open();

            adapter.Fill(datadet);

            conn.Close();

        }

        return datadet;

    }

     

    /// <summary>

    /// 执行查询,并返回查询的Table

    /// </summary>

    /// <param name="tableIndex"></param>

    /// <returns></returns>

    public System.Data.DataTable ExecuteDataSet(int tableIndex)

    {

        System.Data.DataSet datadet = ExecuteDataSet();

        if (datadet.Tables.Count > 0 && tableIndex < datadet.Tables.Count)

        {

            return datadet.Tables[tableIndex];

        }

        else

        {

            return null;

        }

    }

     

    /// <summary>

    /// 执行查询,并返回查询的Table

    /// </summary>

    /// <returns></returns>

    public System.Data.DataTable ExecuteDataTable()

    {

        System.Data.DataTable table = new System.Data.DataTable();

        using (conn)

        {

            System.Data.SqlClient.SqlDataAdapter adapter = new System.Data.SqlClient.SqlDataAdapter();

            adapter.SelectCommand = cmd;

            conn.Open();

            adapter.Fill(table);

            conn.Close();

        }

        return table;

    }

    DataProvider提供ExecuteReaderExecuteNonQueryExecuteScalarExecuteDataSetExecuteDataTable方法,向使用者封装了两种不同的信息:

    对执行数据访问的过程(Open后要Close等)已经在执行过程中的辅助对象(DataAdapter)信息。使用者仅需要简单的调用上述的方法,既可以得到他所关注的数据。

    1.5实现DataProvider参数部分

    SqlDataProvider类实现(参数部分)

    /// <summary>

    /// 添加一个Variant类型数据

    /// </summary>

    /// <param name="parname"></param>

    /// <param name="value"></param>

    public void AddParameters(string parname, object value)

    {

        cmd.Parameters.Add(parname, System.Data.SqlDbType.Variant).Value = value;

    }

     

    /// <summary>

    /// 添加一个Bit类型数据

    /// </summary>

    /// <param name="parname"></param>

    /// <param name="value"></param>

    public void AddParameters(string parname, bool value)

    {

        cmd.Parameters.Add(parname, System.Data.SqlDbType.Bit).Value = value;

    }

     

    /// <summary>

    /// 添加一个TinyInt类型数据

    /// </summary>

    /// <param name="parname"></param>

    /// <param name="value"></param>

    public void AddParameters(string parname, byte value)

    {

        cmd.Parameters.Add(parname, System.Data.SqlDbType.TinyInt).Value = value;

    }

     

    /// <summary>

    /// 添加一个SmallInt类型数据

    /// </summary>

    /// <param name="parname"></param>

    /// <param name="value"></param>

    public void AddParameters(string parname, short value)

    {

        cmd.Parameters.Add(parname, System.Data.SqlDbType.SmallInt).Value = value;

    }

     

    /// <summary>

    /// 添加一个Int类型数据

    /// </summary>

    /// <param name="parname"></param>

    /// <param name="value"></param>

    public void AddParameters(string parname, int value)

    {

        cmd.Parameters.Add(parname, System.Data.SqlDbType.Int).Value = value;

    }

     

    /// <summary>

    /// 添加一个BigInt类型数据

    /// </summary>

    /// <param name="parname"></param>

    /// <param name="value"></param>

    public void AddParameters(string parname, long value)

    {

        cmd.Parameters.Add(parname, System.Data.SqlDbType.BigInt).Value = value;

    }

     

     

    /// <summary>

    /// 添加一张图片

    /// </summary>

    /// <param name="parname"></param>

    /// <param name="value"></param>

    public void AddParameters(string parname, System.Drawing.Bitmap value)

    {

        System.IO.MemoryStream ms = new System.IO.MemoryStream();

        value.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);

        AddParameters(parname, ms.ToArray(), ByteArrayFamily.Image);

    }

     

     

    /// <summary>

    /// 添加一个Timestamp类型

    /// </summary>

    /// <param name="parname"></param>

    /// <param name="value"></param>

    public void AddParameters(string parname, byte[] value)

    {

        AddParameters(parname, value, ByteArrayFamily.Timestamp);

    }

     

    /// <summary>

    /// 添加一个字节数组族类型数据

    /// </summary>

    /// <param name="parname"></param>

    /// <param name="value"></param>

    /// <param name="dateType"></param>

    public void AddParameters(string parname, byte[] value, ByteArrayFamily dataType)

    {

        cmd.Parameters.Add(parname, DataTypeAdapter.ConvertSqlDbType(dataType)).Value = value;

    }

     

     

     

    /// <summary>

    /// 添加一个字符类型数据,默认是NVarChar,长度是value.Length

    /// </summary>

    /// <param name="parname"></param>

    /// <param name="value"></param>

    public void AddParameters(string parname, string value)

    {

        AddParameters(parname, value, StringFamily.NVarChar, value.Length);

    }

     

    /// <summary>

    /// 添加一个字符族类型数据

    /// </summary>

    /// <param name="parname"></param>

    /// <param name="value"></param>

    /// <param name="length"></param>

    public void AddParameters(string parname, string value, int size)

    {

        AddParameters(parname, value, StringFamily.NVarChar, size);

    }

     

     

     

    /// <summary>

    /// 添加一个字符族类型数据

    /// </summary>

    /// <param name="parname"></param>

    /// <param name="value"></param>

    /// <param name="dateType"></param>

    /// <param name="length"></param>

    public void AddParameters(string parname, string value, StringFamily dataType)

    {

        AddParameters(parname, value,dataType, value.Length);

    }

     

    /// <summary>

    /// 添加一个字符族类型数据

    /// </summary>

    /// <param name="parname"></param>

    /// <param name="value"></param>

    /// <param name="dateType"></param>

    /// <param name="size"></param>

    public void AddParameters(string parname, string value, StringFamily dataType, int size)

    {

        cmd.Parameters.Add(parname, DataTypeAdapter.ConvertSqlDbType(dataType), size).Value = value;

    }

     

     

    /// <summary>

    /// 添加一个SmallDateTime类型数据

    /// </summary>

    /// <param name="parname"></param>

    /// <param name="value"></param>

    public void AddParameters(string parname, DateTime value)

    {

        AddParameters(parname, value, DateFamily.SmallDateTime);

    }

     

    /// <summary>

    /// 添加一个日期族类型数据

    /// </summary>

    /// <param name="parname"></param>

    /// <param name="value"></param>

    /// <param name="dateType"></param>

    public void AddParameters(string parname, DateTime value, DateFamily dataType)

    {

        cmd.Parameters.Add(parname, DataTypeAdapter.ConvertSqlDbType(dataType)).Value = value;

    }

     

    /// <summary>

    /// 添加一个Decimal类型数据

    /// </summary>

    /// <param name="parname"></param>

    /// <param name="value"></param>

    public void AddParameters(string parname, decimal value)

    {

        cmd.Parameters.Add(parname, System.Data.SqlDbType.Decimal).Value = value;

    }

     

    /// <summary>

    /// 添加Float类型数据

    /// </summary>

    /// <param name="parname"></param>

    /// <param name="value"></param>

    public void AddParameters(string parname, float value)

    {

        cmd.Parameters.Add(parname, System.Data.SqlDbType.Float).Value = value;

    }

     

    /// <summary>

    /// 添加一个UniqueIdentifier类型数据

    /// </summary>

    /// <param name="parname"></param>

    /// <param name="value"></param>

    public void AddParameters(string parname, System.Guid value)

    {

        cmd.Parameters.Add(parname, System.Data.SqlDbType.UniqueIdentifier).Value = value;

    }

    ADO.Net对参数的处理冗长的很,需要很多代码,我们的DataProvider通过重载简单的实现了对参数的处理,使用者在大多数情况下只需要提供两个参数:参数的名称和值。DataProvider和根据值的类型推算应该使用具体的哪个System.Data.SqlDbType

    1.6定义C#SQL数据类型的关系

    不过,另人烦恼的是C#的数据类型和SQL的数据类型不是简单的一对一的关系,而是一对多的复杂关系,我们需要有一个方法来适配数据类型的不同。

    数据类型的关系定义

    /// <summary>

    /// C#对于的SQL类型

    /// </summary>

    public enum StringFamily

    {

        Char,

        NChar,

        NText,

        NVarChar,

        Text,

        VarChar   

    }

     

    /// <summary>

    /// C#对于的SQL类型

    /// </summary>

    public enum DateFamily

    {

        DateTime,

        SmallDateTime,

        Date,

        Time,

        DateTime2,

        DateTimeOffset   

    }

     

    /// <summary>

    /// C#对于的SQL类型

    /// </summary>

    public enum ByteArrayFamily

    {

        Binary,

        Image,

        Timestamp,

        VarBinary

    }

    1.7定义数据类型的适配器

    DataTypeAdapter的定义

    /// <summary>

    /// SqlDbType数据类型和.NET Framework数据类型的适配器

    /// </summary>

    public static class DataTypeAdapter

    {

        /// <summary>

        /// 将.NET Framework数据类型适配为SqlDbType数据类型

        /// </summary>

        /// <param name="data"></param>

        /// <returns></returns>

        public static System.Data.SqlDbType ConvertSqlDbType(StringFamily data)

        {

            switch (data)

            {

                case StringFamily.Char:

                    return System.Data.SqlDbType.Char;

                case StringFamily.NChar:

                    return System.Data.SqlDbType.NChar;

                case StringFamily.NText:

                    return System.Data.SqlDbType.NText;

                case StringFamily.NVarChar:

                    return System.Data.SqlDbType.NVarChar;

                case StringFamily.Text:

                    return System.Data.SqlDbType.Text;

                default:

                    return System.Data.SqlDbType.VarChar;

            }

        }

     

        /// <summary>

        /// 将.NET Framework数据类型适配为SqlDbType数据类型

        /// </summary>

        /// <param name="data"></param>

        /// <returns></returns>

        public static System.Data.SqlDbType ConvertSqlDbType(DateFamily data)

        {

            switch (data)

            {

                case DateFamily.Date:

                    return System.Data.SqlDbType.Date;

                case DateFamily.DateTime:

                    return System.Data.SqlDbType.DateTime;

                case DateFamily.DateTime2:

                    return System.Data.SqlDbType.DateTime2;

                case DateFamily.DateTimeOffset:

                    return System.Data.SqlDbType.DateTimeOffset;

                case DateFamily.SmallDateTime:

                    return System.Data.SqlDbType.SmallDateTime;

                default:

                    return System.Data.SqlDbType.Time;

            }

        }

     

        /// <summary>

        /// 将.NET Framework数据类型适配为SqlDbType数据类型

        /// </summary>

        /// <param name="data"></param>

        /// <returns></returns>

        public static System.Data.SqlDbType ConvertSqlDbType(ByteArrayFamily data)

        {

            switch (data)

            {

                case ByteArrayFamily.Binary:

                    return System.Data.SqlDbType.Binary;

                case ByteArrayFamily.Image:

                    return System.Data.SqlDbType.Image;

                case ByteArrayFamily.Timestamp:

                    return System.Data.SqlDbType.Timestamp;

                default:

                    return System.Data.SqlDbType.VarBinary;

            }

        }

     

    }

    通过上述的数据类型适配,我们将使用者和ADO.Net直接的具体关系弱耦合了。

  • 相关阅读:
    PAT Advanced 1044 Shopping in Mars (25) [⼆分查找]
    PAT Advanced 1029 Median (25) [two pointers]
    PAT Advanced 1010 Radix(25) [⼆分法]
    PAT Basic 1070 结绳(25) [排序,贪⼼]
    PAT Basic 1023 组个最⼩数 (20) [贪⼼算法]
    PAT Basic 1020 ⽉饼 (25) [贪⼼算法]
    PAT Advanced 1070 Mooncake (25) [贪⼼算法]
    PAT Advanced 1067 Sort with Swap(0,*) (25) [贪⼼算法]
    PAT Advanced 1038 Recover the Smallest Number (30) [贪⼼算法]
    PAT Advanced 1037 Magic Coupon (25) [贪⼼算法]
  • 原文地址:https://www.cnblogs.com/shyleoking/p/1336554.html
Copyright © 2020-2023  润新知