说明:此篇文章是给那些和我一样仍在使用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. PostgreSQL psql中如何查看快捷功能的对应函数

    在psql中,我们可以通过一系列的的快捷命令查看数据库元素,如:\d 查看当前搜索路径下的表,那么内部用到的SQL语句是什么呢,可以通过命令来设置是否打印出来: apple=# \set ECHO_H ...

  2. [置顶] Android 打包apk无敌报错

    前言: 这个问题从昨天上午一直到现在,请教了很多大佬,都没有给出确定的解决方案,可能他们也没碰到过可能,不过还是挺感谢他们的建议,一直到今天中午午休,我一直都在想这个问题,就是下面的这个,看了国内很多 ...

  3. SVN的 安装

    关于svn的安装,如图分别是服务端和客户端 下载地址:http://subversion.apache.org/packages.html 1.双击VisualSVN,点下一步,选择目录,就可以,很简 ...

  4. 斯特灵(Stirling)数

    http://zh.wikipedia.org/wiki/%E6%96%AF%E7%89%B9%E7%81%B5%E6%95%B0 第一类:n个元素分成k个非空循环排列(环)的方法总数 递推式:s(n ...

  5. mysql下,保存时间时具体时间丢失,只保存了日期的问题

    将日志信息记入数据库时增加了一个时间字段,发现存入数据库时只保留了日期,而没有时分秒信息. 我这边环境是(SRPINGMVC+Mybatis,mysql版本5.6.28以上),java层使用类型为ja ...

  6. java利用freemarker导出world

    一.简单导出(不含循环导出) 1.新建一个word文件.如下图: 2.使用word将文件另存为xml的格式 3.编辑xml文件内容,将'用户名'替换成-> ${username}.'简介'替换成 ...

  7. 【转】Windows消息投递流程:一般窗口消息投递(WM_LBUTTONCLICK)

    原文网址:http://blog.csdn.net/hyhnoproblem/article/details/6182646 本例通过在单文档程序的视图中添加WM_LBUTTONCLICK消息处理函数 ...

  8. winodws同步时间命令

    首先,你应该判断你的两台域控制器,哪一台担任PDC角色(默认的域内权威的时间服务源). 判断方法很简单,单击“开始”,单击“运行”,键入dsa.msc,然后点确定.这时会打开“Active Direc ...

  9. C语言 字符串处理函数 转自 http://blog.chinaunix.net/uid-25885064-id-3175049.html

     C字符串处理函数 2012-04-13 18:14:16 分类: C/C++ void *memccpy (void *dest, const void *src, int c, size_t n) ...

  10. app添加引导页

    1.设置guide.html 2.登陆或者主页面引用guide.html mui.plusReady(function() { //读取本地存储,检查是否为首次启动 决定是否显示引导页 var sho ...