• 一、打造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直接的具体关系弱耦合了。

  • 相关阅读:
    ASP.NET编程的十大技巧
    C#学习心得(转)
    POJ 1177 Picture (线段树)
    POJ 3067 Japan (树状数组)
    POJ 2828 Buy Tickets (线段树)
    POJ 1195 Mobile phones (二维树状数组)
    HDU 4235 Flowers (线段树)
    POJ 2886 Who Gets the Most Candies? (线段树)
    POJ 2418 Cows (树状数组)
    HDU 4339 Query (线段树)
  • 原文地址:https://www.cnblogs.com/shyleoking/p/1336554.html
Copyright © 2020-2023  润新知