一、打造DataProvider

一、打造DataProvider

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

1.1定义DataProvide

定义SqlDataProvider类

   
   
   
   
  1. /// <summary>  
  2. /// SQL数据提供者的实现  
  3. /// </summary>  
  4. public class SqlDataProvider : DataProviders.IDataProvider  
  5. {  

1.2定义DataProviders.IDataProvider

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

定义DataProviders.IDataProvider接口

   
   
   
   
  1. public interface IDataProvider  
  2. {  
  3. void AddParameters(string parname, Guid value);  
  4. void AddParameters(string parname, long value);  
  5. void AddParameters(string parname, string value);  
  6. void AddParameters(string parname, string value, DataProviders.StringFamily dataType);  
  7. void AddParameters(string parname, string value, DataProviders.StringFamily dataType, int size);  
  8. void AddParameters(string parname, float value);  
  9. void AddParameters(string parname, decimal value);  
  10. void AddParameters(string parname, DateTime value);  
  11. void AddParameters(string parname, DateTime value, DataProviders.DateFamily dataType);  
  12. void AddParameters(string parname, int value);  
  13. void AddParameters(string parname, object value);  
  14. void AddParameters(string parname, System.Drawing.Bitmap value);  
  15. void AddParameters(string parname, byte[] value);  
  16. void AddParameters(string parname, byte[] value, DataProviders.ByteArrayFamily dataType);  
  17. void AddParameters(string parname, bool value);  
  18. void AddParameters(string parname, short value);  
  19. void AddParameters(string parname, byte value);  
  20. System.Data.CommandType CommandType { get; set; }  
  21. string ConnectionString { get; }  
  22. System.Data.DataSet ExecuteDataSet();  
  23. System.Data.DataTable ExecuteDataTable();  
  24. void ExecuteReader(ReadData readData);  
  25. int ExecuteNonQuery();  
  26. object ExecuteScalar();  
  27. string SQL { get; set; }  
  28. }  
  29. public delegate void ReadData(System.Data.IDataReader dataReadre); 

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

1.3实现DataProvider基础部分

SqlDataProvider类实现(基础部分)

   
   
   
   
  1. private static System.Data.SqlClient.SqlConnection conn;  
  2. private System.Data.SqlClient.SqlCommand cmd;  
  3. /// <summary>  
  4. /// 默认构造函数  
  5. /// </summary>  
  6. public SqlDataProvider()  
  7. {   
  8. }  
  9. /// <summary>  
  10. /// 接受连接字符串  
  11. /// </summary>  
  12. /// <param name="connstr"></param>  
  13. public SqlDataProvider(string connstr)  
  14. : this(connstr, "")  
  15. {  
  16. }  
  17. /// <summary>  
  18. /// 接受连接字符串和sql字符串  
  19. /// </summary>  
  20. /// <param name="connstr"></param>  
  21. /// <param name="sql"></param>  
  22. public SqlDataProvider(string connstr, string sql)  
  23. {  
  24. conn = new System.Data.SqlClient.SqlConnection(connstr);  
  25. cmd = new System.Data.SqlClient.SqlCommand();  
  26. cmd.Connection = conn;  
  27. cmd.CommandText = sql;  
  28. }  
  29. /// <summary>  
  30. /// 需要执行的SQL命令  
  31. /// </summary>  
  32. public string SQL  
  33. {  
  34. set 
  35. {  
  36. cmd.CommandText = value;  
  37. }  
  38. get  
  39. {  
  40. return cmd.CommandText;  
  41. }  
  42. }  
  43. /// <summary>  
  44. /// 当前的连接字符串  
  45. /// </summary>  
  46. public string ConnectionString  
  47. {  
  48. get  
  49. {  
  50. return conn.ConnectionString;  
  51. }  
  52. }  
  53. /// <summary>  
  54. /// 设置命令的类型  
  55. /// </summary>  
  56. public System.Data.CommandType CommandType  
  57. {  
  58. set 
  59. {  
  60. cmd.CommandType = value;  
  61. }  
  62. get  
  63. {  
  64. return cmd.CommandType;  
  65. }  

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

1.4实现DataProvider数据执行部分

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

   
   
   
   
  1. /// <summary>  
  2. /// 将SqlDataReader提交给具体的委托器处理  
  3. /// </summary>  
  4. /// <param name="readData"></param>  
  5. public void ExecuteReader(ReadData readData)  
  6. {  
  7. using (conn)  
  8. {  
  9. conn.Open();  
  10. System.Data.SqlClient.SqlDataReader dr = cmd.ExecuteReader();  
  11. readData(dr);  
  12. conn.Close();  
  13. }  
  14. }  
  15. /// <summary>  
  16. /// 对连接执行 Transact-SQL 语句并返回受影响的行数  
  17. /// </summary>  
  18. /// <returns></returns>  
  19. public int ExecuteNonQuery()  
  20. {  
  21. int result = -1;  
  22. using (conn)  
  23. {  
  24. conn.Open();  
  25. result = cmd.ExecuteNonQuery();  
  26. conn.Close();  
  27. }  
  28. return result;  
  29. }  
  30. /// <summary>  
  31. /// 执行查询,并返回查询所返回的结果集中第一行的第一列。忽略其他列或行  
  32. /// </summary>  
  33. /// <returns></returns>  
  34. public object ExecuteScalar()  
  35. {  
  36. object result = null;  
  37. using (conn)  
  38. {  
  39. conn.Open();  
  40. result = cmd.ExecuteScalar();  
  41. conn.Close();  
  42. }  
  43. return result;  
  44. }  
  45. /// <summary>  
  46. /// 执行查询,并返回查询的DataSet  
  47. /// </summary>  
  48. /// <returns></returns>  
  49. public System.Data.DataSet ExecuteDataSet()  
  50. {  
  51. System.Data.DataSet datadet = new System.Data.DataSet();  
  52. using (conn)  
  53. {  
  54. System.Data.SqlClient.SqlDataAdapter adapter = new System.Data.SqlClient.SqlDataAdapter();  
  55. adapter.SelectCommand = cmd;  
  56. conn.Open();  
  57. adapter.Fill(datadet);  
  58. conn.Close();  
  59. }  
  60. return datadet;  
  61. }  
  62. /// <summary>  
  63. /// 执行查询,并返回查询的Table 
  64. /// </summary>  
  65. /// <param name="tableIndex"></param>  
  66. /// <returns></returns>  
  67. public System.Data.DataTable ExecuteDataSet(int tableIndex)  
  68. {  
  69. System.Data.DataSet datadet = ExecuteDataSet();  
  70. if (datadet.Tables.Count > 0 && tableIndex < datadet.Tables.Count)  
  71. {  
  72. return datadet.Tables[tableIndex];  
  73. }  
  74. else 
  75. {  
  76. return null;  
  77. }  
  78. }  
  79. /// <summary>  
  80. /// 执行查询,并返回查询的Table 
  81. /// </summary>  
  82. /// <returns></returns>  
  83. public System.Data.DataTable ExecuteDataTable()  
  84. {  
  85. System.Data.DataTable table = new System.Data.DataTable();  
  86. using (conn)  
  87. {  
  88. System.Data.SqlClient.SqlDataAdapter adapter = new System.Data.SqlClient.SqlDataAdapter();  
  89. adapter.SelectCommand = cmd;  
  90. conn.Open();  
  91. adapter.Fill(table);  
  92. conn.Close();  
  93. }  
  94. return table;  

DataProvider提供ExecuteReader、ExecuteNonQuery、ExecuteScalar、ExecuteDataSet和ExecuteDataTable方法,向使用者封装了两种不同的信息:

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

1.5实现DataProvider参数部分

SqlDataProvider类实现(参数部分)

   
   
   
   
  1. /// <summary>  
  2. /// 添加一个Variant类型数据  
  3. /// </summary>  
  4. /// <param name="parname"></param>  
  5. /// <param name="value"></param>  
  6. public void AddParameters(string parname, object value)  
  7. {  
  8. cmd.Parameters.Add(parname, System.Data.SqlDbType.Variant).Value = value;  
  9. }  
  10. /// <summary>  
  11. /// 添加一个Bit类型数据  
  12. /// </summary>  
  13. /// <param name="parname"></param>  
  14. /// <param name="value"></param>  
  15. public void AddParameters(string parname, bool value)  
  16. {  
  17. cmd.Parameters.Add(parname, System.Data.SqlDbType.Bit).Value = value;  
  18. }  
  19. /// <summary>  
  20. /// 添加一个TinyInt类型数据  
  21. /// </summary>  
  22. /// <param name="parname"></param>  
  23. /// <param name="value"></param>  
  24. public void AddParameters(string parname, byte value)  
  25. {  
  26. cmd.Parameters.Add(parname, System.Data.SqlDbType.TinyInt).Value = value;  
  27. }  
  28. /// <summary>  
  29. /// 添加一个SmallInt类型数据  
  30. /// </summary>  
  31. /// <param name="parname"></param>  
  32. /// <param name="value"></param>  
  33. public void AddParameters(string parname, short value)  
  34. {  
  35. cmd.Parameters.Add(parname, System.Data.SqlDbType.SmallInt).Value = value;  
  36. }  
  37. /// <summary>  
  38. /// 添加一个Int类型数据  
  39. /// </summary>  
  40. /// <param name="parname"></param>  
  41. /// <param name="value"></param>  
  42. public void AddParameters(string parname, int value)  
  43. {  
  44. cmd.Parameters.Add(parname, System.Data.SqlDbType.Int).Value = value;  
  45. }  
  46. /// <summary>  
  47. /// 添加一个BigInt类型数据  
  48. /// </summary>  
  49. /// <param name="parname"></param>  
  50. /// <param name="value"></param>  
  51. public void AddParameters(string parname, long value)  
  52. {  
  53. cmd.Parameters.Add(parname, System.Data.SqlDbType.BigInt).Value = value;  
  54. }  
  55. /// <summary>  
  56. /// 添加一张图片  
  57. /// </summary>  
  58. /// <param name="parname"></param>  
  59. /// <param name="value"></param>  
  60. public void AddParameters(string parname, System.Drawing.Bitmap value)  
  61. {  
  62. System.IO.MemoryStream ms = new System.IO.MemoryStream();  
  63. value.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);  
  64. AddParameters(parname, ms.ToArray(), ByteArrayFamily.Image);  
  65. }  
  66. /// <summary>  
  67. /// 添加一个Timestamp类型  
  68. /// </summary>  
  69. /// <param name="parname"></param>  
  70. /// <param name="value"></param>  
  71. public void AddParameters(string parname, byte[] value)  
  72. {  
  73. AddParameters(parname, value, ByteArrayFamily.Timestamp);  
  74. }  
  75. /// <summary>  
  76. /// 添加一个字节数组族类型数据  
  77. /// </summary>  
  78. /// <param name="parname"></param>  
  79. /// <param name="value"></param>  
  80. /// <param name="dateType"></param>  
  81. public void AddParameters(string parname, byte[] value, ByteArrayFamily dataType)  
  82. {  
  83. cmd.Parameters.Add(parname, DataTypeAdapter.ConvertSqlDbType(dataType)).Value = value;  
  84. }  
  85. /// <summary>  
  86. /// 添加一个字符类型数据,默认是NVarChar,长度是value.Length  
  87. /// </summary>  
  88. /// <param name="parname"></param>  
  89. /// <param name="value"></param>  
  90. public void AddParameters(string parname, string value)  
  91. {  
  92. AddParameters(parname, value, StringFamily.NVarChar, value.Length);  
  93. }  
  94. /// <summary>  
  95. /// 添加一个字符族类型数据  
  96. /// </summary>  
  97. /// <param name="parname"></param>  
  98. /// <param name="value"></param>  
  99. /// <param name="length"></param>  
  100. public void AddParameters(string parname, string value, int size)  
  101. {  
  102. AddParameters(parname, value, StringFamily.NVarChar, size);  
  103. }  
  104. /// <summary>  
  105. /// 添加一个字符族类型数据  
  106. /// </summary>  
  107. /// <param name="parname"></param>  
  108. /// <param name="value"></param>  
  109. /// <param name="dateType"></param>  
  110. /// <param name="length"></param>  
  111. public void AddParameters(string parname, string value, StringFamily dataType)  
  112. {  
  113. AddParameters(parname, value,dataType, value.Length);  
  114. }  
  115. /// <summary>  
  116. /// 添加一个字符族类型数据  
  117. /// </summary>  
  118. /// <param name="parname"></param>  
  119. /// <param name="value"></param>  
  120. /// <param name="dateType"></param>  
  121. /// <param name="size"></param>  
  122. public void AddParameters(string parname, string value, StringFamily dataType, int size)  
  123. {  
  124. cmd.Parameters.Add(parname, DataTypeAdapter.ConvertSqlDbType(dataType), size).Value = value;  
  125. }  
  126. /// <summary>  
  127. /// 添加一个SmallDateTime类型数据  
  128. /// </summary>  
  129. /// <param name="parname"></param>  
  130. /// <param name="value"></param>  
  131. public void AddParameters(string parname, DateTime value)  
  132. {  
  133. AddParameters(parname, value, DateFamily.SmallDateTime);  
  134. }  
  135. /// <summary>  
  136. /// 添加一个日期族类型数据  
  137. /// </summary>  
  138. /// <param name="parname"></param>  
  139. /// <param name="value"></param>  
  140. /// <param name="dateType"></param>  
  141. public void AddParameters(string parname, DateTime value, DateFamily dataType)  
  142. {  
  143. cmd.Parameters.Add(parname, DataTypeAdapter.ConvertSqlDbType(dataType)).Value = value;  
  144. }  
  145. /// <summary>  
  146. /// 添加一个Decimal类型数据  
  147. /// </summary>  
  148. /// <param name="parname"></param>  
  149. /// <param name="value"></param>  
  150. public void AddParameters(string parname, decimal value)  
  151. {  
  152. cmd.Parameters.Add(parname, System.Data.SqlDbType.Decimal).Value = value;  
  153. }  
  154. /// <summary>  
  155. /// 添加Float类型数据  
  156. /// </summary>  
  157. /// <param name="parname"></param>  
  158. /// <param name="value"></param>  
  159. public void AddParameters(string parname, float value)  
  160. {  
  161. cmd.Parameters.Add(parname, System.Data.SqlDbType.Float).Value = value;  
  162. }  
  163. /// <summary>  
  164. /// 添加一个UniqueIdentifier类型数据  
  165. /// </summary>  
  166. /// <param name="parname"></param>  
  167. /// <param name="value"></param>  
  168. public void AddParameters(string parname, System.Guid value)  
  169. {  
  170. cmd.Parameters.Add(parname, System.Data.SqlDbType.UniqueIdentifier).Value = value;  

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

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

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

数据类型的关系定义

   
   
   
   
  1. /// <summary>  
  2. /// C#对于的SQL类型  
  3. /// </summary>  
  4. public enum StringFamily  
  5. {  
  6. Char,  
  7. NChar,  
  8. NText,  
  9. NVarChar,  
  10. Text,  
  11. VarChar   
  12. }  
  13. /// <summary>  
  14. /// C#对于的SQL类型  
  15. /// </summary>  
  16. public enum DateFamily  
  17. {  
  18. DateTime,  
  19. SmallDateTime,  
  20. Date,  
  21. Time,  
  22. DateTime2,  
  23. DateTimeOffset   
  24. }  
  25. /// <summary>  
  26. /// C#对于的SQL类型  
  27. /// </summary>  
  28. public enum ByteArrayFamily  
  29. {  
  30. Binary,  
  31. Image,  
  32. Timestamp,  
  33. VarBinary  

1.7定义数据类型的适配器

DataTypeAdapter的定义 

   
   
   
   
  1. /// <summary>  
  2. /// SqlDbType数据类型和.NET Framework数据类型的适配器  
  3. /// </summary>  
  4. public static class DataTypeAdapter  
  5. {  
  6. /// <summary>  
  7. /// 将.NET Framework数据类型适配为SqlDbType数据类型  
  8. /// </summary>  
  9. /// <param name="data"></param>  
  10. /// <returns></returns>  
  11. public static System.Data.SqlDbType ConvertSqlDbType(StringFamily data)  
  12. {  
  13. switch (data)  
  14. {  
  15. case StringFamily.Char:  
  16. return System.Data.SqlDbType.Char;  
  17. case StringFamily.NChar:  
  18. return System.Data.SqlDbType.NChar;  
  19. case StringFamily.NText:  
  20. return System.Data.SqlDbType.NText;  
  21. case StringFamily.NVarChar:  
  22. return System.Data.SqlDbType.NVarChar;  
  23. case StringFamily.Text:  
  24. return System.Data.SqlDbType.Text;  
  25. default:  
  26. return System.Data.SqlDbType.VarChar;  
  27. }  
  28. }  
  29. /// <summary>  
  30. /// 将.NET Framework数据类型适配为SqlDbType数据类型  
  31. /// </summary>  
  32. /// <param name="data"></param>  
  33. /// <returns></returns>  
  34. public static System.Data.SqlDbType ConvertSqlDbType(DateFamily data)  
  35. {  
  36. switch (data)  
  37. {  
  38. case DateFamily.Date:  
  39. return System.Data.SqlDbType.Date;  
  40. case DateFamily.DateTime:  
  41. return System.Data.SqlDbType.DateTime;  
  42. case DateFamily.DateTime2:  
  43. return System.Data.SqlDbType.DateTime2;  
  44. case DateFamily.DateTimeOffset:  
  45. return System.Data.SqlDbType.DateTimeOffset;  
  46. case DateFamily.SmallDateTime:  
  47. return System.Data.SqlDbType.SmallDateTime;  
  48. default:  
  49. return System.Data.SqlDbType.Time;  
  50. }  
  51. }  
  52. /// <summary>  
  53. /// 将.NET Framework数据类型适配为SqlDbType数据类型  
  54. /// </summary>  
  55. /// <param name="data"></param>  
  56. /// <returns></returns>  
  57. public static System.Data.SqlDbType ConvertSqlDbType(ByteArrayFamily data)  
  58. {  
  59. switch (data)  
  60. {  
  61. case ByteArrayFamily.Binary:  
  62. return System.Data.SqlDbType.Binary;  
  63. case ByteArrayFamily.Image:  
  64. return System.Data.SqlDbType.Image;  
  65. case ByteArrayFamily.Timestamp:  
  66. return System.Data.SqlDbType.Timestamp;  
  67. default:  
  68. return System.Data.SqlDbType.VarBinary;  
  69. }  
  70. }  

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

 

你可能感兴趣的:(职场,Class,封装,休闲,提供者)