说明:此篇文章是给那些和我一样仍在使用ADO.NET访问数据库的.NET开发人员写的,因为某些原因,比如还在使用.NET3.0以下版本开发.NET应用或者所使用的数据库对ORM支持不是很好,或者是对ORM的性能有所怀疑(其实在访问量不是很大的情况下没有必要过分追求性能的极限)等等,这部分人仍在使用传统的ADO.NET来访问数据库,他们或手写或采用代码生成工具来生成实体类和增删改查的SQL语句,在将DataTable或者DataReader转换成对应的实体类的时候仍需要一行行写代码,本类就是为了解决这个问题的,可以用几个类来实现方便快捷的转换。本类库在SQL Server/MySQL/SQLite下测试通过,由于条件有限未在所有的数据库下测试,如果有问题请在此留言或者在周公的微博留言(http://weibo.com/zhoufoxcn)。
其实在写这套类库之前,去年周公就写了两篇有关的文章,一篇叫《用C#打造自己的实体转换器》,另一篇叫《利用ADO.NET的体系架构打造通用的数据库访问通用类》,本篇的代码就是在这两篇文章的基础上经过实际应用修改而成,主要是修正了几个问题:1.如果在SELECT子句的字段中不包含对应实体类的某个属性,那么该属性的值就为它对应Type的默认值(如int,short为0,引用类型为null),而不是像以前那样用Ignorable,因为有些属性可能在某个查询中需要而在另外一个查询中不需要,采用Ignorable这样的Attribute的话太武断;2.修正了在泛型类型时的错误;3.在类的属性类型中除了支持常见数据类型(数值类型、可空类型和string)之外,还支持byte[]这种常见的数据类型。
本类库共有5个类:DbProviderType、ProviderFactory、DbUtility、EntityReader、ColumnNameAttribute。
其中DbProviderType、ProviderFactory、DbUtility三个类的相关代码如下:

[csharp] view plaincopy

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Data.Common;
  5. namespace NetSkycn.Data
  6. {
  7. /// <summary>
  8. /// 通用数据库访问类,封装了对数据库的常见操作
  9. /// 作者:周公
  10. /// 创建日期:2011-07-18
  11. /// 修改日期:2012-04-12
  12. /// 新浪微博地址:http://weibo.com/zhoufoxcn
  13. /// </summary>
  14. public sealed class DbUtility
  15. {
  16. public string ConnectionString { get; set; }
  17. private DbProviderFactory providerFactory;
  18. /// <summary>
  19. /// 构造函数
  20. /// </summary>
  21. /// <param name="connectionString">数据库连接字符串</param>
  22. /// <param name="providerType">数据库类型枚举,参见<paramref name="providerType"/></param>
  23. public DbUtility(string connectionString, DbProviderType providerType)
  24. {
  25. ConnectionString = connectionString;
  26. providerFactory = ProviderFactory.GetDbProviderFactory(providerType);
  27. if (providerFactory == null)
  28. {
  29. throw new ArgumentException("Can't load DbProviderFactory for given value of providerType");
  30. }
  31. }
  32. /// <summary>
  33. /// 对数据库执行增删改操作,返回受影响的行数。
  34. /// </summary>
  35. /// <param name="sql">要执行的增删改的SQL语句</param>
  36. /// <param name="parameters">执行增删改语句所需要的参数</param>
  37. /// <returns></returns>
  38. public int ExecuteNonQuery(string sql, IList<DbParameter> parameters)
  39. {
  40. return ExecuteNonQuery(sql, parameters, CommandType.Text);
  41. }
  42. /// <summary>
  43. /// 对数据库执行增删改操作,返回受影响的行数。
  44. /// </summary>
  45. /// <param name="sql">要执行的增删改的SQL语句</param>
  46. /// <param name="parameters">执行增删改语句所需要的参数</param>
  47. /// <param name="commandType">执行的SQL语句的类型</param>
  48. /// <returns></returns>
  49. public int ExecuteNonQuery(string sql, IList<DbParameter> parameters, CommandType commandType)
  50. {
  51. using (DbCommand command = CreateDbCommand(sql, parameters, commandType))
  52. {
  53. command.Connection.Open();
  54. int affectedRows = command.ExecuteNonQuery();
  55. command.Connection.Close();
  56. return affectedRows;
  57. }
  58. }
  59. /// <summary>
  60. /// 执行一个查询语句,返回一个关联的DataReader实例
  61. /// </summary>
  62. /// <param name="sql">要执行的查询语句</param>
  63. /// <param name="parameters">执行SQL查询语句所需要的参数</param>
  64. /// <returns></returns>
  65. public DbDataReader ExecuteReader(string sql, IList<DbParameter> parameters)
  66. {
  67. return ExecuteReader(sql, parameters, CommandType.Text);
  68. }
  69. /// <summary>
  70. /// 执行一个查询语句,返回一个关联的DataReader实例
  71. /// </summary>
  72. /// <param name="sql">要执行的查询语句</param>
  73. /// <param name="parameters">执行SQL查询语句所需要的参数</param>
  74. /// <param name="commandType">执行的SQL语句的类型</param>
  75. /// <returns></returns>
  76. public DbDataReader ExecuteReader(string sql, IList<DbParameter> parameters, CommandType commandType)
  77. {
  78. DbCommand command = CreateDbCommand(sql, parameters, commandType);
  79. command.Connection.Open();
  80. return command.ExecuteReader(CommandBehavior.CloseConnection);
  81. }
  82. /// <summary>
  83. /// 执行一个查询语句,返回一个包含查询结果的DataTable
  84. /// </summary>
  85. /// <param name="sql">要执行的查询语句</param>
  86. /// <param name="parameters">执行SQL查询语句所需要的参数</param>
  87. /// <returns></returns>
  88. public DataTable ExecuteDataTable(string sql, IList<DbParameter> parameters)
  89. {
  90. return ExecuteDataTable(sql, parameters, CommandType.Text);
  91. }
  92. /// <summary>
  93. /// 执行一个查询语句,返回一个包含查询结果的DataTable
  94. /// </summary>
  95. /// <param name="sql">要执行的查询语句</param>
  96. /// <param name="parameters">执行SQL查询语句所需要的参数</param>
  97. /// <param name="commandType">执行的SQL语句的类型</param>
  98. /// <returns></returns>
  99. public DataTable ExecuteDataTable(string sql, IList<DbParameter> parameters, CommandType commandType)
  100. {
  101. using (DbCommand command = CreateDbCommand(sql, parameters, commandType))
  102. {
  103. using (DbDataAdapter adapter = providerFactory.CreateDataAdapter())
  104. {
  105. adapter.SelectCommand = command;
  106. DataTable data = new DataTable();
  107. adapter.Fill(data);
  108. return data;
  109. }
  110. }
  111. }
  112. /// <summary>
  113. /// 执行一个查询语句,返回查询结果的第一行第一列
  114. /// </summary>
  115. /// <param name="sql">要执行的查询语句</param>
  116. /// <param name="parameters">执行SQL查询语句所需要的参数</param>
  117. /// <returns></returns>
  118. public Object ExecuteScalar(string sql, IList<DbParameter> parameters)
  119. {
  120. return ExecuteScalar(sql, parameters, CommandType.Text);
  121. }
  122. /// <summary>
  123. /// 执行一个查询语句,返回查询结果的第一行第一列
  124. /// </summary>
  125. /// <param name="sql">要执行的查询语句</param>
  126. /// <param name="parameters">执行SQL查询语句所需要的参数</param>
  127. /// <param name="commandType">执行的SQL语句的类型</param>
  128. /// <returns></returns>
  129. public Object ExecuteScalar(string sql, IList<DbParameter> parameters, CommandType commandType)
  130. {
  131. using (DbCommand command = CreateDbCommand(sql, parameters, commandType))
  132. {
  133. command.Connection.Open();
  134. object result = command.ExecuteScalar();
  135. command.Connection.Close();
  136. return result;
  137. }
  138. }
  139. /// <summary>
  140. /// 查询多个实体集合
  141. /// </summary>
  142. /// <typeparam name="T">返回的实体集合类型</typeparam>
  143. /// <param name="sql">要执行的查询语句</param>
  144. /// <param name="parameters">执行SQL查询语句所需要的参数</param>
  145. /// <returns></returns>
  146. public List<T> QueryForList<T>(string sql, IList<DbParameter> parameters) where T : new()
  147. {
  148. return QueryForList<T>(sql, parameters, CommandType.Text);
  149. }
  150. /// <summary>
  151. ///  查询多个实体集合
  152. /// </summary>
  153. /// <typeparam name="T">返回的实体集合类型</typeparam>
  154. /// <param name="sql">要执行的查询语句</param>
  155. /// <param name="parameters">执行SQL查询语句所需要的参数</param>
  156. /// <param name="commandType">执行的SQL语句的类型</param>
  157. /// <returns></returns>
  158. public List<T> QueryForList<T>(string sql, IList<DbParameter> parameters, CommandType commandType) where T : new()
  159. {
  160. DataTable data = ExecuteDataTable(sql, parameters, commandType);
  161. return EntityReader.GetEntities<T>(data);
  162. }
  163. /// <summary>
  164. /// 查询单个实体
  165. /// </summary>
  166. /// <typeparam name="T">返回的实体集合类型</typeparam>
  167. /// <param name="sql">要执行的查询语句</param>
  168. /// <param name="parameters">执行SQL查询语句所需要的参数</param>
  169. /// <returns></returns>
  170. public T QueryForObject<T>(string sql, IList<DbParameter> parameters) where T : new()
  171. {
  172. return QueryForObject<T>(sql, parameters, CommandType.Text);
  173. }
  174. /// <summary>
  175. /// 查询单个实体
  176. /// </summary>
  177. /// <typeparam name="T">返回的实体集合类型</typeparam>
  178. /// <param name="sql">要执行的查询语句</param>
  179. /// <param name="parameters">执行SQL查询语句所需要的参数</param>
  180. /// <param name="commandType">执行的SQL语句的类型</param>
  181. /// <returns></returns>
  182. public T QueryForObject<T>(string sql, IList<DbParameter> parameters, CommandType commandType) where T : new()
  183. {
  184. List <T> list= QueryForList<T>(sql, parameters, commandType);
  185. if (list.Count > 0)
  186. {
  187. return list[0];
  188. }
  189. else
  190. {
  191. return default(T);
  192. }
  193. }
  194. public DbParameter CreateDbParameter(string name, object value)
  195. {
  196. return CreateDbParameter(name, ParameterDirection.Input, value);
  197. }
  198. public DbParameter CreateDbParameter(string name, ParameterDirection parameterDirection, object value)
  199. {
  200. DbParameter parameter = providerFactory.CreateParameter();
  201. parameter.ParameterName = name;
  202. parameter.Value = value;
  203. parameter.Direction = parameterDirection;
  204. return parameter;
  205. }
  206. /// <summary>
  207. /// 创建一个DbCommand对象
  208. /// </summary>
  209. /// <param name="sql">要执行的查询语句</param>
  210. /// <param name="parameters">执行SQL查询语句所需要的参数</param>
  211. /// <param name="commandType">执行的SQL语句的类型</param>
  212. /// <returns></returns>
  213. private DbCommand CreateDbCommand(string sql, IList<DbParameter> parameters, CommandType commandType)
  214. {
  215. DbConnection connection = providerFactory.CreateConnection();
  216. DbCommand command = providerFactory.CreateCommand();
  217. connection.ConnectionString = ConnectionString;
  218. command.CommandText = sql;
  219. command.CommandType = commandType;
  220. command.Connection = connection;
  221. if (!(parameters == null || parameters.Count == 0))
  222. {
  223. foreach (DbParameter parameter in parameters)
  224. {
  225. command.Parameters.Add(parameter);
  226. }
  227. }
  228. return command;
  229. }
  230. }
  231. /// <summary>
  232. /// 数据库类型枚举
  233. /// </summary>
  234. public enum DbProviderType : byte
  235. {
  236. SqlServer,
  237. MySql,
  238. SQLite,
  239. Oracle,
  240. ODBC,
  241. OleDb,
  242. Firebird,
  243. PostgreSql,
  244. DB2,
  245. Informix,
  246. SqlServerCe
  247. }
  248. /// <summary>
  249. /// DbProviderFactory工厂类
  250. /// </summary>
  251. public class ProviderFactory
  252. {
  253. private static Dictionary<DbProviderType, string> providerInvariantNames = new Dictionary<DbProviderType, string>();
  254. private static Dictionary<DbProviderType, DbProviderFactory> providerFactoies = new Dictionary<DbProviderType, DbProviderFactory>(20);
  255. static ProviderFactory()
  256. {
  257. //加载已知的数据库访问类的程序集
  258. providerInvariantNames.Add(DbProviderType.SqlServer, "System.Data.SqlClient");
  259. providerInvariantNames.Add(DbProviderType.OleDb, "System.Data.OleDb");
  260. providerInvariantNames.Add(DbProviderType.ODBC, "System.Data.ODBC");
  261. providerInvariantNames.Add(DbProviderType.Oracle, "Oracle.DataAccess.Client");
  262. providerInvariantNames.Add(DbProviderType.MySql, "MySql.Data.MySqlClient");
  263. providerInvariantNames.Add(DbProviderType.SQLite, "System.Data.SQLite");
  264. providerInvariantNames.Add(DbProviderType.Firebird, "FirebirdSql.Data.Firebird");
  265. providerInvariantNames.Add(DbProviderType.PostgreSql, "Npgsql");
  266. providerInvariantNames.Add(DbProviderType.DB2, "IBM.Data.DB2.iSeries");
  267. providerInvariantNames.Add(DbProviderType.Informix, "IBM.Data.Informix");
  268. providerInvariantNames.Add(DbProviderType.SqlServerCe, "System.Data.SqlServerCe");
  269. }
  270. /// <summary>
  271. /// 获取指定数据库类型对应的程序集名称
  272. /// </summary>
  273. /// <param name="providerType">数据库类型枚举</param>
  274. /// <returns></returns>
  275. public static string GetProviderInvariantName(DbProviderType providerType)
  276. {
  277. return providerInvariantNames[providerType];
  278. }
  279. /// <summary>
  280. /// 获取指定类型的数据库对应的DbProviderFactory
  281. /// </summary>
  282. /// <param name="providerType">数据库类型枚举</param>
  283. /// <returns></returns>
  284. public static DbProviderFactory GetDbProviderFactory(DbProviderType providerType)
  285. {
  286. //如果还没有加载,则加载该DbProviderFactory
  287. if (!providerFactoies.ContainsKey(providerType))
  288. {
  289. providerFactoies.Add(providerType, ImportDbProviderFactory(providerType));
  290. }
  291. return providerFactoies[providerType];
  292. }
  293. /// <summary>
  294. /// 加载指定数据库类型的DbProviderFactory
  295. /// </summary>
  296. /// <param name="providerType">数据库类型枚举</param>
  297. /// <returns></returns>
  298. private static DbProviderFactory ImportDbProviderFactory(DbProviderType providerType)
  299. {
  300. string providerName = providerInvariantNames[providerType];
  301. DbProviderFactory factory = null;
  302. try
  303. {
  304. //从全局程序集中查找
  305. factory = DbProviderFactories.GetFactory(providerName);
  306. }
  307. catch (ArgumentException e)
  308. {
  309. factory = null;
  310. }
  311. return factory;
  312. }
  313. }
  314. }

其中EntityReader、ColumnNameAttribute的代码如下:

[csharp] view plaincopy

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Data.Common;
  5. using System.Reflection;
  6. namespace NetSkycn.Data
  7. {
  8. /// <summary>
  9. /// 实体阅读器类,可以从DataTable中或者DbDataReader的实例中将数据转换成对应的示例
  10. /// 作者:周公
  11. /// 创建日期:2011-07-21
  12. /// 修改日期:2012-04-12
  13. /// 新浪微博地址:http://weibo.com/zhoufoxcn
  14. /// </summary>
  15. public sealed class EntityReader
  16. {
  17. private const BindingFlags BindingFlag = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
  18. //将类型与该类型所有的可写且未被忽略属性之间建立映射
  19. private static Dictionary<Type, Dictionary<string, PropertyInfo>> propertyMappings = new Dictionary<Type, Dictionary<string, PropertyInfo>>();
  20. /// <summary>
  21. /// 将DataTable中的所有数据转换成List>T<集合
  22. /// </summary>
  23. /// <typeparam name="T">DataTable中每条数据可以转换的数据类型</typeparam>
  24. /// <param name="dataTable">包含有可以转换成数据类型T的数据集合</param>
  25. /// <returns></returns>
  26. public static List<T> GetEntities<T>(DataTable dataTable) where T : new()
  27. {
  28. if (dataTable == null)
  29. {
  30. throw new ArgumentNullException("dataTable");
  31. }
  32. //如果T的类型满足以下条件:字符串、ValueType或者是Nullable<ValueType>
  33. if (typeof(T) == typeof(string)||typeof(T)==typeof(byte[])|| typeof(T).IsValueType)
  34. {
  35. return GetSimpleEntities<T>(dataTable);
  36. }
  37. else
  38. {
  39. return GetComplexEntities<T>(dataTable);
  40. }
  41. }
  42. /// <summary>
  43. /// 将DbDataReader中的所有数据转换成List>T<集合
  44. /// </summary>
  45. /// <typeparam name="T">DbDataReader中每条数据可以转换的数据类型</typeparam>
  46. /// <param name="dataTable">包含有可以转换成数据类型T的DbDataReader实例</param>
  47. /// <returns></returns>
  48. public static List<T> GetEntities<T>(DbDataReader reader) where T : new()
  49. {
  50. List<T> list = new List<T>();
  51. if (reader == null)
  52. {
  53. throw new ArgumentNullException("reader");
  54. }
  55. //如果T的类型满足以下条件:字符串、ValueType或者是Nullable<ValueType>
  56. if (typeof(T) == typeof(string) || typeof(T).IsValueType)
  57. {
  58. return GetSimpleEntities<T>(reader);
  59. }
  60. else
  61. {
  62. return GetComplexEntities<T>(reader);
  63. }
  64. }
  65. /// <summary>
  66. /// 从DataTable中将每一行的第一列转换成T类型的数据
  67. /// </summary>
  68. /// <typeparam name="T">要转换的目标数据类型</typeparam>
  69. /// <param name="dataTable">包含有可以转换成数据类型T的数据集合</param>
  70. /// <returns></returns>
  71. private static List<T> GetSimpleEntities<T>(DataTable dataTable) where T : new()
  72. {
  73. List<T> list = new List<T>();
  74. foreach (DataRow row in dataTable.Rows)
  75. {
  76. list.Add((T)GetValueFromObject(row[0], typeof(T)));
  77. }
  78. return list;
  79. }
  80. /// <summary>
  81. /// 将指定的 Object 的值转换为指定类型的值。
  82. /// </summary>
  83. /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
  84. /// <param name="targetType">要转换的目标数据类型</param>
  85. /// <returns></returns>
  86. private static object GetValueFromObject(object value, Type targetType)
  87. {
  88. if (targetType == typeof(string))//如果要将value转换成string类型
  89. {
  90. return GetString(value);
  91. }
  92. else if(targetType==typeof(byte[]))//如果要将value转换成byte[]类型
  93. {
  94. return GetBinary(value);
  95. }
  96. else if (targetType.IsGenericType)//如果目标类型是泛型
  97. {
  98. return GetGenericValueFromObject(value, targetType);
  99. }
  100. else//如果是基本数据类型(包括数值类型、枚举和Guid)
  101. {
  102. return GetNonGenericValueFromObject(value, targetType);
  103. }
  104. }
  105. /// <summary>
  106. /// 从DataTable中读取复杂数据类型集合
  107. /// </summary>
  108. /// <typeparam name="T">要转换的目标数据类型</typeparam>
  109. /// <param name="dataTable">包含有可以转换成数据类型T的数据集合</param>
  110. /// <returns></returns>
  111. private static List<T> GetComplexEntities<T>(DataTable dataTable) where T : new()
  112. {
  113. if (!propertyMappings.ContainsKey(typeof(T)))
  114. {
  115. GenerateTypePropertyMapping(typeof(T));
  116. }
  117. List<T> list = new List<T>();
  118. Dictionary<string, PropertyInfo> properties = propertyMappings[typeof(T)];
  119. T t;
  120. foreach (DataRow row in dataTable.Rows)
  121. {
  122. t = new T();
  123. foreach (KeyValuePair<string, PropertyInfo> item in properties)
  124. {
  125. //如果对应的属性名出现在数据源的列中则获取值并设置给对应的属性
  126. if (row[item.Key] != null)
  127. {
  128. item.Value.SetValue(t, GetValueFromObject(row[item.Key], item.Value.PropertyType), null);
  129. }
  130. }
  131. list.Add(t);
  132. }
  133. return list;
  134. }
  135. /// <summary>
  136. /// 从DbDataReader的实例中读取复杂的数据类型
  137. /// </summary>
  138. /// <typeparam name="T">要转换的目标类</typeparam>
  139. /// <param name="reader">DbDataReader的实例</param>
  140. /// <returns></returns>
  141. private static List<T> GetComplexEntities<T>(DbDataReader reader) where T : new()
  142. {
  143. if (!propertyMappings.ContainsKey(typeof(T)))//检查当前是否已经有该类与类的可写属性之间的映射
  144. {
  145. GenerateTypePropertyMapping(typeof(T));
  146. }
  147. List<T> list = new List<T>();
  148. Dictionary<string, PropertyInfo> properties = propertyMappings[typeof(T)];
  149. T t;
  150. while (reader.Read())
  151. {
  152. t = new T();
  153. foreach (KeyValuePair<string, PropertyInfo> item in properties)
  154. {
  155. //如果对应的属性名出现在数据源的列中则获取值并设置给对应的属性
  156. if (reader[item.Key] != null)
  157. {
  158. item.Value.SetValue(t, GetValueFromObject(reader[item.Key], item.Value.PropertyType), null);
  159. }
  160. }
  161. list.Add(t);
  162. }
  163. return list;
  164. }
  165. /// <summary>
  166. /// 从DbDataReader的实例中读取简单数据类型(String,ValueType)
  167. /// </summary>
  168. /// <typeparam name="T">目标数据类型</typeparam>
  169. /// <param name="reader">DbDataReader的实例</param>
  170. /// <returns></returns>
  171. private static List<T> GetSimpleEntities<T>(DbDataReader reader)
  172. {
  173. List<T> list = new List<T>();
  174. while (reader.Read())
  175. {
  176. list.Add((T)GetValueFromObject(reader[0], typeof(T)));
  177. }
  178. return list;
  179. }
  180. /// <summary>
  181. /// 将Object转换成字符串类型
  182. /// </summary>
  183. /// <param name="value">object类型的实例</param>
  184. /// <returns></returns>
  185. private static object GetString(object value)
  186. {
  187. return Convert.ToString(value);
  188. }
  189. /// <summary>
  190. /// 将指定的 Object 的值转换为指定枚举类型的值。
  191. /// </summary>
  192. /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
  193. /// <param name="targetType"></param>
  194. /// <returns></returns>
  195. private static object GetEnum(object value, Type targetType)
  196. {
  197. return Enum.Parse(targetType, value.ToString());
  198. }
  199. /// <summary>
  200. /// 将指定的 Object 的值转换为指定枚举类型的值。
  201. /// </summary>
  202. /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
  203. /// <returns></returns>
  204. private static object GetBoolean(object value)
  205. {
  206. if (value is Boolean)
  207. {
  208. return value;
  209. }
  210. else
  211. {
  212. byte byteValue = (byte)GetByte(value);
  213. if (byteValue == 0)
  214. {
  215. return false;
  216. }
  217. else
  218. {
  219. return true;
  220. }
  221. }
  222. }
  223. /// <summary>
  224. /// 将指定的 Object 的值转换为指定枚举类型的值。
  225. /// </summary>
  226. /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
  227. /// <returns></returns>
  228. private static object GetByte(object value)
  229. {
  230. if (value is Byte)
  231. {
  232. return value;
  233. }
  234. else
  235. {
  236. return byte.Parse(value.ToString());
  237. }
  238. }
  239. /// <summary>
  240. /// 将指定的 Object 的值转换为指定枚举类型的值。
  241. /// </summary>
  242. /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
  243. /// <returns></returns>
  244. private static object GetSByte(object value)
  245. {
  246. if (value is SByte)
  247. {
  248. return value;
  249. }
  250. else
  251. {
  252. return SByte.Parse(value.ToString());
  253. }
  254. }
  255. /// <summary>
  256. /// 将指定的 Object 的值转换为指定枚举类型的值。
  257. /// </summary>
  258. /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
  259. /// <returns></returns>
  260. private static object GetChar(object value)
  261. {
  262. if (value is Char)
  263. {
  264. return value;
  265. }
  266. else
  267. {
  268. return Char.Parse(value.ToString());
  269. }
  270. }
  271. /// <summary>
  272. /// 将指定的 Object 的值转换为指定枚举类型的值。
  273. /// </summary>
  274. /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
  275. /// <returns></returns>
  276. private static object GetGuid(object value)
  277. {
  278. if (value is Guid)
  279. {
  280. return value;
  281. }
  282. else
  283. {
  284. return new Guid(value.ToString());
  285. }
  286. }
  287. /// <summary>
  288. /// 将指定的 Object 的值转换为指定枚举类型的值。
  289. /// </summary>
  290. /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
  291. /// <returns></returns>
  292. private static object GetInt16(object value)
  293. {
  294. if (value is Int16)
  295. {
  296. return value;
  297. }
  298. else
  299. {
  300. return Int16.Parse(value.ToString());
  301. }
  302. }
  303. /// <summary>
  304. /// 将指定的 Object 的值转换为指定枚举类型的值。
  305. /// </summary>
  306. /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
  307. /// <returns></returns>
  308. private static object GetUInt16(object value)
  309. {
  310. if (value is UInt16)
  311. {
  312. return value;
  313. }
  314. else
  315. {
  316. return UInt16.Parse(value.ToString());
  317. }
  318. }
  319. /// <summary>
  320. /// 将指定的 Object 的值转换为指定枚举类型的值。
  321. /// </summary>
  322. /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
  323. /// <returns></returns>
  324. private static object GetInt32(object value)
  325. {
  326. if (value is Int32)
  327. {
  328. return value;
  329. }
  330. else
  331. {
  332. return Int32.Parse(value.ToString());
  333. }
  334. }
  335. /// <summary>
  336. /// 将指定的 Object 的值转换为指定枚举类型的值。
  337. /// </summary>
  338. /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
  339. /// <returns></returns>
  340. private static object GetUInt32(object value)
  341. {
  342. if (value is UInt32)
  343. {
  344. return value;
  345. }
  346. else
  347. {
  348. return UInt32.Parse(value.ToString());
  349. }
  350. }
  351. /// <summary>
  352. /// 将指定的 Object 的值转换为指定枚举类型的值。
  353. /// </summary>
  354. /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
  355. /// <returns></returns>
  356. private static object GetInt64(object value)
  357. {
  358. if (value is Int64)
  359. {
  360. return value;
  361. }
  362. else
  363. {
  364. return Int64.Parse(value.ToString());
  365. }
  366. }
  367. /// <summary>
  368. /// 将指定的 Object 的值转换为指定枚举类型的值。
  369. /// </summary>
  370. /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
  371. /// <returns></returns>
  372. private static object GetUInt64(object value)
  373. {
  374. if (value is UInt64)
  375. {
  376. return value;
  377. }
  378. else
  379. {
  380. return UInt64.Parse(value.ToString());
  381. }
  382. }
  383. /// <summary>
  384. /// 将指定的 Object 的值转换为指定枚举类型的值。
  385. /// </summary>
  386. /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
  387. /// <returns></returns>
  388. private static object GetSingle(object value)
  389. {
  390. if (value is Single)
  391. {
  392. return value;
  393. }
  394. else
  395. {
  396. return Single.Parse(value.ToString());
  397. }
  398. }
  399. /// <summary>
  400. /// 将指定的 Object 的值转换为指定枚举类型的值。
  401. /// </summary>
  402. /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
  403. /// <returns></returns>
  404. private static object GetDouble(object value)
  405. {
  406. if (value is Double)
  407. {
  408. return value;
  409. }
  410. else
  411. {
  412. return Double.Parse(value.ToString());
  413. }
  414. }
  415. /// <summary>
  416. /// 将指定的 Object 的值转换为指定枚举类型的值。
  417. /// </summary>
  418. /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
  419. /// <returns></returns>
  420. private static object GetDecimal(object value)
  421. {
  422. if (value is Decimal)
  423. {
  424. return value;
  425. }
  426. else
  427. {
  428. return Decimal.Parse(value.ToString());
  429. }
  430. }
  431. /// <summary>
  432. /// 将指定的 Object 的值转换为指定枚举类型的值。
  433. /// </summary>
  434. /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
  435. /// <returns></returns>
  436. private static object GetDateTime(object value)
  437. {
  438. if (value is DateTime)
  439. {
  440. return value;
  441. }
  442. else
  443. {
  444. return DateTime.Parse(value.ToString());
  445. }
  446. }
  447. /// <summary>
  448. /// 将指定的 Object 的值转换为指定枚举类型的值。
  449. /// </summary>
  450. /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
  451. /// <returns></returns>
  452. private static object GetTimeSpan(object value)
  453. {
  454. if (value is TimeSpan)
  455. {
  456. return value;
  457. }
  458. else
  459. {
  460. return TimeSpan.Parse(value.ToString());
  461. }
  462. }
  463. /// <summary>
  464. /// 将指定的 Object 的值转换为指定枚举类型的值。
  465. /// </summary>
  466. /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
  467. /// <returns></returns>
  468. private static byte[] GetBinary(object value)
  469. {
  470. //如果该字段为NULL则返回null
  471. if (value == DBNull.Value)
  472. {
  473. return null;
  474. }
  475. else if (value is Byte[])
  476. {
  477. return (byte[])(value);
  478. }
  479. else
  480. {
  481. return null;
  482. }
  483. }
  484. /// <summary>
  485. /// 将Object类型数据转换成对应的可空数值类型表示
  486. /// </summary>
  487. /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
  488. /// <param name="targetType">可空数值类型</param>
  489. /// <returns></returns>
  490. private static object GetGenericValueFromObject(object value, Type targetType)
  491. {
  492. if (value == DBNull.Value)
  493. {
  494. return null;
  495. }
  496. else
  497. {
  498. //获取可空数值类型对应的基本数值类型,如int?->int,long?->long
  499. //Type nonGenericType = genericTypeMappings[targetType];
  500. Type nonGenericType = targetType.GetGenericArguments()[0];
  501. return GetNonGenericValueFromObject(value, nonGenericType);
  502. }
  503. }
  504. /// <summary>
  505. /// 将指定的 Object 的值转换为指定类型的值。
  506. /// </summary>
  507. /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
  508. /// <param name="targetType">目标对象的类型</param>
  509. /// <returns></returns>
  510. private static object GetNonGenericValueFromObject(object value, Type targetType)
  511. {
  512. if (targetType.IsEnum)//因为
  513. {
  514. return GetEnum(value, targetType);
  515. }
  516. else
  517. {
  518. switch (targetType.Name)
  519. {
  520. case "Byte": return GetByte(value);
  521. case "SByte": return GetSByte(value);
  522. case "Char": return GetChar(value);
  523. case "Boolean": return GetBoolean(value);
  524. case "Guid": return GetGuid(value);
  525. case "Int16": return GetInt16(value);
  526. case "UInt16": return GetUInt16(value);
  527. case "Int32": return GetInt32(value);
  528. case "UInt32": return GetUInt32(value);
  529. case "Int64": return GetInt64(value);
  530. case "UInt64": return GetUInt64(value);
  531. case "Single": return GetSingle(value);
  532. case "Double": return GetDouble(value);
  533. case "Decimal": return GetDecimal(value);
  534. case "DateTime": return GetDateTime(value);
  535. case "TimeSpan": return GetTimeSpan(value);
  536. default: return null;
  537. }
  538. }
  539. }
  540. /// <summary>
  541. /// 获取该类型中属性与数据库字段的对应关系映射
  542. /// </summary>
  543. /// <param name="type"></param>
  544. private static void GenerateTypePropertyMapping(Type type)
  545. {
  546. if (type != null)
  547. {
  548. PropertyInfo[] properties = type.GetProperties(BindingFlag);
  549. Dictionary<string, PropertyInfo> propertyColumnMapping = new Dictionary<string, PropertyInfo>(properties.Length);
  550. string description = string.Empty;
  551. Attribute[] attibutes = null;
  552. string columnName = string.Empty;
  553. foreach (PropertyInfo p in properties)
  554. {
  555. columnName = string.Empty;
  556. attibutes = Attribute.GetCustomAttributes(p);
  557. foreach (Attribute attribute in attibutes)
  558. {
  559. //检查是否设置了ColumnName属性
  560. if (attribute.GetType() == typeof(ColumnNameAttribute))
  561. {
  562. columnName = ((ColumnNameAttribute)attribute).ColumnName;
  563. break;
  564. }
  565. }
  566. //如果该属性是可读并且未被忽略的,则有可能在实例化该属性对应的类时用得上
  567. if (p.CanWrite)
  568. {
  569. //如果没有设置ColumnName属性,则直接将该属性名作为数据库字段的映射
  570. if (string.IsNullOrEmpty(columnName))
  571. {
  572. columnName = p.Name;
  573. }
  574. propertyColumnMapping.Add(columnName, p);
  575. }
  576. }
  577. propertyMappings.Add(type, propertyColumnMapping);
  578. }
  579. }
  580. }
  581. /// <summary>
  582. /// 自定义属性,用于指示如何从DataTable或者DbDataReader中读取类的属性值
  583. /// </summary>
  584. public class ColumnNameAttribute : Attribute
  585. {
  586. /// <summary>
  587. /// 类属性对应的列名
  588. /// </summary>
  589. public string ColumnName { get; set; }
  590. /// <summary>
  591. /// 构造函数
  592. /// </summary>
  593. /// <param name="columnName">类属性对应的列名</param>
  594. public ColumnNameAttribute(string columnName)
  595. {
  596. ColumnName = columnName;
  597. }
  598. }
  599. }

注意:因为在machine.config中的<system.data> <DbProviderFactories>已经存在如下内容:

  1. <system.data>
  2. <DbProviderFactories>
  3. <add name="Odbc Data Provider" invariant="System.Data.Odbc" description=".Net Framework Data Provider for Odbc" type="System.Data.Odbc.OdbcFactory, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
  4. <add name="OleDb Data Provider" invariant="System.Data.OleDb" description=".Net Framework Data Provider for OleDb" type="System.Data.OleDb.OleDbFactory, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
  5. <add name="OracleClient Data Provider" invariant="System.Data.OracleClient" description=".Net Framework Data Provider for Oracle" type="System.Data.OracleClient.OracleClientFactory, System.Data.OracleClient, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
  6. <add name="SqlClient Data Provider" invariant="System.Data.SqlClient" description=".Net Framework Data Provider for SqlServer" type="System.Data.SqlClient.SqlClientFactory, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
  7. <add name="Microsoft SQL Server Compact Data Provider" invariant="System.Data.SqlServerCe.3.5" description=".NET Framework Data Provider for Microsoft SQL Server Compact" type="System.Data.SqlServerCe.SqlCeProviderFactory, System.Data.SqlServerCe, Version=3.5.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91" />
  8. </DbProviderFactories>
  9. </system.data>

所以如果你采用以上的四种方式之一来访问数据,那么就不需要采取任何设置,但如果你是访问其它类型的数据库(如MySQL,SQLite)那么就需要在当前config文件的根节点下增加<system.data> <DbProviderFactories>节点,并在节点中增加你访问的数据库的方式,以下是可能值之一(注意并不是全部,添加时也不不必将下面的配置全部添加进去,只添加你所使用的数据库对应的方式即可):

[html] view plaincopy

 
  1. <add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" />
  2. <add name="Informix Data Provider" invariant="IBM.Data.Informix" description=".Net Framework Data Provider for Informix" type="IBM.Data.Informix.IfxFactory, IBM.Data.Informix" />
  3. <add name="DB2 Data Provider" invariant="IBM.Data.DB2.iSeries" description=".Net Framework Data Provider for DB2 iSeries" type="IBM.Data.DB2.iSeries.DB2Factory, IBM.Data.DB2.iSeries" />
  4. <add name="Firebird Data Provider" invariant="FirebirdSql.Data.FirebirdClient" description="Firebird" type="FirebirdSql.Data.FirebirdClient.FirebirdClientFactory, FirebirdSql.Data.FirebirdClient"/>
  5. <add name="Oracle Data Provider" invariant="Oracle.DataAccess.Client" description=".Net Framework Data Provider for Oracle" type="Oracle.DataAccess.Client.OracleClientFactory, Oracle.DataAccess" />
  6. <add name="PostgreSQL Data Provider Data Provider" invariant="Npgsql" description=".Net Framework Data Provider for PostgreSQL" type="Npgsql.NpgsqlFactory, Npgsql" />

比如在项目中使用了SQLite数据库,那么有关这部分的配置如下(这里讲述可能相当啰嗦,但也是没办法的事情,因为周公经常收到询问此处细节的留言):

[html] view plaincopy

 
    1. <?xml version="1.0" encoding="utf-8" ?>
    2. <configuration>
    3. <system.data>
    4. <DbProviderFactories>
    5. <add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" />
    6. </DbProviderFactories>
    7. </system.data>
    8. </configuration>

C#通用数据访问类库的更多相关文章

  1. ClownFish:比手写代码还快的通用数据访问层

    http://www.cnblogs.com/fish-li/archive/2012/07/17/ClownFish.html 阅读目录 开始 ClownFish是什么? 比手写代码还快的执行速度 ...

  2. C# 通用数据访问类(SqlHelper)

    [转]C# 通用数据访问类(SqlHelper) 注:本文转自http://www.tzwhx.com/newOperate/html/3/31/312/13080.htmlVisual C# 动态操 ...

  3. ADO.NET笔记——使用通用数据访问

    相关知识: 前面所有示例,君是访问特定的数据库(SQL Server),因此注入SqlConnection.SqlCommand.SqlDataReader.SqlDataAdapter等类名都添加了 ...

  4. 基于Spring4+Hibernate4的通用数据访问层+业务逻辑层(Dao层+Service层)设计与实现!

    基于泛型的依赖注入.当我们的项目中有很多的Model时,相应的Dao(DaoImpl),Service(ServiceImpl)也会增多. 而我们对这些Model的操作很多都是类似的,下面是我举出的一 ...

  5. 自己写的Dapper通用数据访问层

    using Microsoft.Practices.EnterpriseLibrary.Data; using Microsoft.Practices.EnterpriseLibrary.Data.O ...

  6. 1.1 DAL数据访问层

    分布式(Distributed)数据访问层(Data Access Layer),简称DAL,是利用MySQL Proxy.Memcached.集群等技术优点而构建的一个架构系统.主要目的是解决高并发 ...

  7. 在 ASP.NET 中创建数据访问和业务逻辑层(转)

    .NET Framework 4 当在 ASP.NET 中处理数据时,可从使用通用软件模式中受益.其中一种模式是将数据访问代码与控制数据访问或提供其他业务规则的业务逻辑代码分开.在此模式中,这两个层均 ...

  8. 高性能JavaScript笔记一(加载和执行、数据访问、DOM编程)

    写在前面 好的书,可能你第一遍并不能领会里面的精魂,当再次细细品评的时候,发现领悟的又是一层新的含义 (这段时间,工作上也不会像从前一样做起来毫不费力,开始有了新的挑战,现在的老大让我既佩服又嫉妒,但 ...

  9. Winform开发框架之通用数据导入导出操作的事务性操作完善

    1.通用数据导入导出操作模块回顾 在我的Winfrom开发框架里面,有一个通用的导入模块,它在默默处理这把规范的Excel数据导入到不同的对象表里面,一直用它来快速完成数据导入的工作.很早在随笔< ...

随机推荐

  1. Python中定时任务框架APScheduler

    前言 大家应该都知道在编程语言中,定时任务是常用的一种调度形式,在Python中也涌现了非常多的调度模块,本文将简要介绍APScheduler的基本使用方法. 一.APScheduler介绍 APSc ...

  2. streamsets stream selector 使用

    stream selector 就是一个选择器,可以方便的对于不同record 的数据进行区分,并执行不同的处理 pipeline flow stream selector 配置 local fs 配 ...

  3. am335x内核初始化路径

    /arch/arm/mach-omap2/board_am335xevm.c中 1.myd_am335x_dev_cfg[]{ evm_nand_init() ... myir_gpio_init() ...

  4. Erlang Web 监控工具

    转自http://www.cnblogs.com/me-sa/archive/2012/04/17/erlang-web-monitor.html  Erlang已经提供了一系列工具查看运行时状态查看 ...

  5. thinkpad t420安装debian需要注意的细节

    关闭双显卡,使用集成显卡,32位可以用独显跑起来,但是64位的wheezy只能兼容集成显卡,不知道为啥,否则会在某些usb插入/或者拔出来以后,重启提示 failed to execute /lib/ ...

  6. android单元测试 activity跳转 以及 input 输入后 测试

    Android junit实现多个Activity跳转测试 分类: Android Junit测试2011-11-14 16:49 1601人阅读 评论(2) 收藏 举报 androidjunitla ...

  7. CentOS 6.7 编译PHP7 make时出现错误:undefined reference to `libiconv_close’

    编辑Makefile文件,找到变量EXTRA_LIBS,并在末尾添上-liconv EXTRA_LIBS = -lcrypt -lz -lexslt -lcrypt -lrt -lmcrypt -ll ...

  8. springcloud(七) feign + Hystrix 整合 、

    之前几章演示的熔断,降级 都是 RestTemplate + Ribbon 和 RestTemplate + Hystrix  ,但是在实际开发并不是这样,实际开发中都是 Feign 远程接口调用. ...

  9. Apache Kylin本地启动

    首先:kylin是一种Online Analytics Platform.    kylin 在Apache的首页是http://kylin.apache.org/cn/.    kylin git代 ...

  10. Python Web框架——Flask

    简介 Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理 ...