C#通用数据访问类库
说明:此篇文章是给那些和我一样仍在使用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三个类的相关代码如下:
- using System;
 - using System.Collections.Generic;
 - using System.Data;
 - using System.Data.Common;
 - namespace NetSkycn.Data
 - {
 - /// <summary>
 - /// 通用数据库访问类,封装了对数据库的常见操作
 - /// 作者:周公
 - /// 创建日期:2011-07-18
 - /// 修改日期:2012-04-12
 - /// 新浪微博地址:http://weibo.com/zhoufoxcn
 - /// </summary>
 - public sealed class DbUtility
 - {
 - public string ConnectionString { get; set; }
 - private DbProviderFactory providerFactory;
 - /// <summary>
 - /// 构造函数
 - /// </summary>
 - /// <param name="connectionString">数据库连接字符串</param>
 - /// <param name="providerType">数据库类型枚举,参见<paramref name="providerType"/></param>
 - public DbUtility(string connectionString, DbProviderType providerType)
 - {
 - ConnectionString = connectionString;
 - providerFactory = ProviderFactory.GetDbProviderFactory(providerType);
 - if (providerFactory == null)
 - {
 - throw new ArgumentException("Can't load DbProviderFactory for given value of providerType");
 - }
 - }
 - /// <summary>
 - /// 对数据库执行增删改操作,返回受影响的行数。
 - /// </summary>
 - /// <param name="sql">要执行的增删改的SQL语句</param>
 - /// <param name="parameters">执行增删改语句所需要的参数</param>
 - /// <returns></returns>
 - public int ExecuteNonQuery(string sql, IList<DbParameter> parameters)
 - {
 - return ExecuteNonQuery(sql, parameters, CommandType.Text);
 - }
 - /// <summary>
 - /// 对数据库执行增删改操作,返回受影响的行数。
 - /// </summary>
 - /// <param name="sql">要执行的增删改的SQL语句</param>
 - /// <param name="parameters">执行增删改语句所需要的参数</param>
 - /// <param name="commandType">执行的SQL语句的类型</param>
 - /// <returns></returns>
 - public int ExecuteNonQuery(string sql, IList<DbParameter> parameters, CommandType commandType)
 - {
 - using (DbCommand command = CreateDbCommand(sql, parameters, commandType))
 - {
 - command.Connection.Open();
 - int affectedRows = command.ExecuteNonQuery();
 - command.Connection.Close();
 - return affectedRows;
 - }
 - }
 - /// <summary>
 - /// 执行一个查询语句,返回一个关联的DataReader实例
 - /// </summary>
 - /// <param name="sql">要执行的查询语句</param>
 - /// <param name="parameters">执行SQL查询语句所需要的参数</param>
 - /// <returns></returns>
 - public DbDataReader ExecuteReader(string sql, IList<DbParameter> parameters)
 - {
 - return ExecuteReader(sql, parameters, CommandType.Text);
 - }
 - /// <summary>
 - /// 执行一个查询语句,返回一个关联的DataReader实例
 - /// </summary>
 - /// <param name="sql">要执行的查询语句</param>
 - /// <param name="parameters">执行SQL查询语句所需要的参数</param>
 - /// <param name="commandType">执行的SQL语句的类型</param>
 - /// <returns></returns>
 - public DbDataReader ExecuteReader(string sql, IList<DbParameter> parameters, CommandType commandType)
 - {
 - DbCommand command = CreateDbCommand(sql, parameters, commandType);
 - command.Connection.Open();
 - return command.ExecuteReader(CommandBehavior.CloseConnection);
 - }
 - /// <summary>
 - /// 执行一个查询语句,返回一个包含查询结果的DataTable
 - /// </summary>
 - /// <param name="sql">要执行的查询语句</param>
 - /// <param name="parameters">执行SQL查询语句所需要的参数</param>
 - /// <returns></returns>
 - public DataTable ExecuteDataTable(string sql, IList<DbParameter> parameters)
 - {
 - return ExecuteDataTable(sql, parameters, CommandType.Text);
 - }
 - /// <summary>
 - /// 执行一个查询语句,返回一个包含查询结果的DataTable
 - /// </summary>
 - /// <param name="sql">要执行的查询语句</param>
 - /// <param name="parameters">执行SQL查询语句所需要的参数</param>
 - /// <param name="commandType">执行的SQL语句的类型</param>
 - /// <returns></returns>
 - public DataTable ExecuteDataTable(string sql, IList<DbParameter> parameters, CommandType commandType)
 - {
 - using (DbCommand command = CreateDbCommand(sql, parameters, commandType))
 - {
 - using (DbDataAdapter adapter = providerFactory.CreateDataAdapter())
 - {
 - adapter.SelectCommand = command;
 - DataTable data = new DataTable();
 - adapter.Fill(data);
 - return data;
 - }
 - }
 - }
 - /// <summary>
 - /// 执行一个查询语句,返回查询结果的第一行第一列
 - /// </summary>
 - /// <param name="sql">要执行的查询语句</param>
 - /// <param name="parameters">执行SQL查询语句所需要的参数</param>
 - /// <returns></returns>
 - public Object ExecuteScalar(string sql, IList<DbParameter> parameters)
 - {
 - return ExecuteScalar(sql, parameters, CommandType.Text);
 - }
 - /// <summary>
 - /// 执行一个查询语句,返回查询结果的第一行第一列
 - /// </summary>
 - /// <param name="sql">要执行的查询语句</param>
 - /// <param name="parameters">执行SQL查询语句所需要的参数</param>
 - /// <param name="commandType">执行的SQL语句的类型</param>
 - /// <returns></returns>
 - public Object ExecuteScalar(string sql, IList<DbParameter> parameters, CommandType commandType)
 - {
 - using (DbCommand command = CreateDbCommand(sql, parameters, commandType))
 - {
 - command.Connection.Open();
 - object result = command.ExecuteScalar();
 - command.Connection.Close();
 - return result;
 - }
 - }
 - /// <summary>
 - /// 查询多个实体集合
 - /// </summary>
 - /// <typeparam name="T">返回的实体集合类型</typeparam>
 - /// <param name="sql">要执行的查询语句</param>
 - /// <param name="parameters">执行SQL查询语句所需要的参数</param>
 - /// <returns></returns>
 - public List<T> QueryForList<T>(string sql, IList<DbParameter> parameters) where T : new()
 - {
 - return QueryForList<T>(sql, parameters, CommandType.Text);
 - }
 - /// <summary>
 - /// 查询多个实体集合
 - /// </summary>
 - /// <typeparam name="T">返回的实体集合类型</typeparam>
 - /// <param name="sql">要执行的查询语句</param>
 - /// <param name="parameters">执行SQL查询语句所需要的参数</param>
 - /// <param name="commandType">执行的SQL语句的类型</param>
 - /// <returns></returns>
 - public List<T> QueryForList<T>(string sql, IList<DbParameter> parameters, CommandType commandType) where T : new()
 - {
 - DataTable data = ExecuteDataTable(sql, parameters, commandType);
 - return EntityReader.GetEntities<T>(data);
 - }
 - /// <summary>
 - /// 查询单个实体
 - /// </summary>
 - /// <typeparam name="T">返回的实体集合类型</typeparam>
 - /// <param name="sql">要执行的查询语句</param>
 - /// <param name="parameters">执行SQL查询语句所需要的参数</param>
 - /// <returns></returns>
 - public T QueryForObject<T>(string sql, IList<DbParameter> parameters) where T : new()
 - {
 - return QueryForObject<T>(sql, parameters, CommandType.Text);
 - }
 - /// <summary>
 - /// 查询单个实体
 - /// </summary>
 - /// <typeparam name="T">返回的实体集合类型</typeparam>
 - /// <param name="sql">要执行的查询语句</param>
 - /// <param name="parameters">执行SQL查询语句所需要的参数</param>
 - /// <param name="commandType">执行的SQL语句的类型</param>
 - /// <returns></returns>
 - public T QueryForObject<T>(string sql, IList<DbParameter> parameters, CommandType commandType) where T : new()
 - {
 - List <T> list= QueryForList<T>(sql, parameters, commandType);
 - if (list.Count > 0)
 - {
 - return list[0];
 - }
 - else
 - {
 - return default(T);
 - }
 - }
 - public DbParameter CreateDbParameter(string name, object value)
 - {
 - return CreateDbParameter(name, ParameterDirection.Input, value);
 - }
 - public DbParameter CreateDbParameter(string name, ParameterDirection parameterDirection, object value)
 - {
 - DbParameter parameter = providerFactory.CreateParameter();
 - parameter.ParameterName = name;
 - parameter.Value = value;
 - parameter.Direction = parameterDirection;
 - return parameter;
 - }
 - /// <summary>
 - /// 创建一个DbCommand对象
 - /// </summary>
 - /// <param name="sql">要执行的查询语句</param>
 - /// <param name="parameters">执行SQL查询语句所需要的参数</param>
 - /// <param name="commandType">执行的SQL语句的类型</param>
 - /// <returns></returns>
 - private DbCommand CreateDbCommand(string sql, IList<DbParameter> parameters, CommandType commandType)
 - {
 - DbConnection connection = providerFactory.CreateConnection();
 - DbCommand command = providerFactory.CreateCommand();
 - connection.ConnectionString = ConnectionString;
 - command.CommandText = sql;
 - command.CommandType = commandType;
 - command.Connection = connection;
 - if (!(parameters == null || parameters.Count == 0))
 - {
 - foreach (DbParameter parameter in parameters)
 - {
 - command.Parameters.Add(parameter);
 - }
 - }
 - return command;
 - }
 - }
 - /// <summary>
 - /// 数据库类型枚举
 - /// </summary>
 - public enum DbProviderType : byte
 - {
 - SqlServer,
 - MySql,
 - SQLite,
 - Oracle,
 - ODBC,
 - OleDb,
 - Firebird,
 - PostgreSql,
 - DB2,
 - Informix,
 - SqlServerCe
 - }
 - /// <summary>
 - /// DbProviderFactory工厂类
 - /// </summary>
 - public class ProviderFactory
 - {
 - private static Dictionary<DbProviderType, string> providerInvariantNames = new Dictionary<DbProviderType, string>();
 - private static Dictionary<DbProviderType, DbProviderFactory> providerFactoies = new Dictionary<DbProviderType, DbProviderFactory>(20);
 - static ProviderFactory()
 - {
 - //加载已知的数据库访问类的程序集
 - providerInvariantNames.Add(DbProviderType.SqlServer, "System.Data.SqlClient");
 - providerInvariantNames.Add(DbProviderType.OleDb, "System.Data.OleDb");
 - providerInvariantNames.Add(DbProviderType.ODBC, "System.Data.ODBC");
 - providerInvariantNames.Add(DbProviderType.Oracle, "Oracle.DataAccess.Client");
 - providerInvariantNames.Add(DbProviderType.MySql, "MySql.Data.MySqlClient");
 - providerInvariantNames.Add(DbProviderType.SQLite, "System.Data.SQLite");
 - providerInvariantNames.Add(DbProviderType.Firebird, "FirebirdSql.Data.Firebird");
 - providerInvariantNames.Add(DbProviderType.PostgreSql, "Npgsql");
 - providerInvariantNames.Add(DbProviderType.DB2, "IBM.Data.DB2.iSeries");
 - providerInvariantNames.Add(DbProviderType.Informix, "IBM.Data.Informix");
 - providerInvariantNames.Add(DbProviderType.SqlServerCe, "System.Data.SqlServerCe");
 - }
 - /// <summary>
 - /// 获取指定数据库类型对应的程序集名称
 - /// </summary>
 - /// <param name="providerType">数据库类型枚举</param>
 - /// <returns></returns>
 - public static string GetProviderInvariantName(DbProviderType providerType)
 - {
 - return providerInvariantNames[providerType];
 - }
 - /// <summary>
 - /// 获取指定类型的数据库对应的DbProviderFactory
 - /// </summary>
 - /// <param name="providerType">数据库类型枚举</param>
 - /// <returns></returns>
 - public static DbProviderFactory GetDbProviderFactory(DbProviderType providerType)
 - {
 - //如果还没有加载,则加载该DbProviderFactory
 - if (!providerFactoies.ContainsKey(providerType))
 - {
 - providerFactoies.Add(providerType, ImportDbProviderFactory(providerType));
 - }
 - return providerFactoies[providerType];
 - }
 - /// <summary>
 - /// 加载指定数据库类型的DbProviderFactory
 - /// </summary>
 - /// <param name="providerType">数据库类型枚举</param>
 - /// <returns></returns>
 - private static DbProviderFactory ImportDbProviderFactory(DbProviderType providerType)
 - {
 - string providerName = providerInvariantNames[providerType];
 - DbProviderFactory factory = null;
 - try
 - {
 - //从全局程序集中查找
 - factory = DbProviderFactories.GetFactory(providerName);
 - }
 - catch (ArgumentException e)
 - {
 - factory = null;
 - }
 - return factory;
 - }
 - }
 - }
 
其中EntityReader、ColumnNameAttribute的代码如下:
- using System;
 - using System.Collections.Generic;
 - using System.Data;
 - using System.Data.Common;
 - using System.Reflection;
 - namespace NetSkycn.Data
 - {
 - /// <summary>
 - /// 实体阅读器类,可以从DataTable中或者DbDataReader的实例中将数据转换成对应的示例
 - /// 作者:周公
 - /// 创建日期:2011-07-21
 - /// 修改日期:2012-04-12
 - /// 新浪微博地址:http://weibo.com/zhoufoxcn
 - /// </summary>
 - public sealed class EntityReader
 - {
 - private const BindingFlags BindingFlag = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
 - //将类型与该类型所有的可写且未被忽略属性之间建立映射
 - private static Dictionary<Type, Dictionary<string, PropertyInfo>> propertyMappings = new Dictionary<Type, Dictionary<string, PropertyInfo>>();
 - /// <summary>
 - /// 将DataTable中的所有数据转换成List>T<集合
 - /// </summary>
 - /// <typeparam name="T">DataTable中每条数据可以转换的数据类型</typeparam>
 - /// <param name="dataTable">包含有可以转换成数据类型T的数据集合</param>
 - /// <returns></returns>
 - public static List<T> GetEntities<T>(DataTable dataTable) where T : new()
 - {
 - if (dataTable == null)
 - {
 - throw new ArgumentNullException("dataTable");
 - }
 - //如果T的类型满足以下条件:字符串、ValueType或者是Nullable<ValueType>
 - if (typeof(T) == typeof(string)||typeof(T)==typeof(byte[])|| typeof(T).IsValueType)
 - {
 - return GetSimpleEntities<T>(dataTable);
 - }
 - else
 - {
 - return GetComplexEntities<T>(dataTable);
 - }
 - }
 - /// <summary>
 - /// 将DbDataReader中的所有数据转换成List>T<集合
 - /// </summary>
 - /// <typeparam name="T">DbDataReader中每条数据可以转换的数据类型</typeparam>
 - /// <param name="dataTable">包含有可以转换成数据类型T的DbDataReader实例</param>
 - /// <returns></returns>
 - public static List<T> GetEntities<T>(DbDataReader reader) where T : new()
 - {
 - List<T> list = new List<T>();
 - if (reader == null)
 - {
 - throw new ArgumentNullException("reader");
 - }
 - //如果T的类型满足以下条件:字符串、ValueType或者是Nullable<ValueType>
 - if (typeof(T) == typeof(string) || typeof(T).IsValueType)
 - {
 - return GetSimpleEntities<T>(reader);
 - }
 - else
 - {
 - return GetComplexEntities<T>(reader);
 - }
 - }
 - /// <summary>
 - /// 从DataTable中将每一行的第一列转换成T类型的数据
 - /// </summary>
 - /// <typeparam name="T">要转换的目标数据类型</typeparam>
 - /// <param name="dataTable">包含有可以转换成数据类型T的数据集合</param>
 - /// <returns></returns>
 - private static List<T> GetSimpleEntities<T>(DataTable dataTable) where T : new()
 - {
 - List<T> list = new List<T>();
 - foreach (DataRow row in dataTable.Rows)
 - {
 - list.Add((T)GetValueFromObject(row[0], typeof(T)));
 - }
 - return list;
 - }
 - /// <summary>
 - /// 将指定的 Object 的值转换为指定类型的值。
 - /// </summary>
 - /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
 - /// <param name="targetType">要转换的目标数据类型</param>
 - /// <returns></returns>
 - private static object GetValueFromObject(object value, Type targetType)
 - {
 - if (targetType == typeof(string))//如果要将value转换成string类型
 - {
 - return GetString(value);
 - }
 - else if(targetType==typeof(byte[]))//如果要将value转换成byte[]类型
 - {
 - return GetBinary(value);
 - }
 - else if (targetType.IsGenericType)//如果目标类型是泛型
 - {
 - return GetGenericValueFromObject(value, targetType);
 - }
 - else//如果是基本数据类型(包括数值类型、枚举和Guid)
 - {
 - return GetNonGenericValueFromObject(value, targetType);
 - }
 - }
 - /// <summary>
 - /// 从DataTable中读取复杂数据类型集合
 - /// </summary>
 - /// <typeparam name="T">要转换的目标数据类型</typeparam>
 - /// <param name="dataTable">包含有可以转换成数据类型T的数据集合</param>
 - /// <returns></returns>
 - private static List<T> GetComplexEntities<T>(DataTable dataTable) where T : new()
 - {
 - if (!propertyMappings.ContainsKey(typeof(T)))
 - {
 - GenerateTypePropertyMapping(typeof(T));
 - }
 - List<T> list = new List<T>();
 - Dictionary<string, PropertyInfo> properties = propertyMappings[typeof(T)];
 - T t;
 - foreach (DataRow row in dataTable.Rows)
 - {
 - t = new T();
 - foreach (KeyValuePair<string, PropertyInfo> item in properties)
 - {
 - //如果对应的属性名出现在数据源的列中则获取值并设置给对应的属性
 - if (row[item.Key] != null)
 - {
 - item.Value.SetValue(t, GetValueFromObject(row[item.Key], item.Value.PropertyType), null);
 - }
 - }
 - list.Add(t);
 - }
 - return list;
 - }
 - /// <summary>
 - /// 从DbDataReader的实例中读取复杂的数据类型
 - /// </summary>
 - /// <typeparam name="T">要转换的目标类</typeparam>
 - /// <param name="reader">DbDataReader的实例</param>
 - /// <returns></returns>
 - private static List<T> GetComplexEntities<T>(DbDataReader reader) where T : new()
 - {
 - if (!propertyMappings.ContainsKey(typeof(T)))//检查当前是否已经有该类与类的可写属性之间的映射
 - {
 - GenerateTypePropertyMapping(typeof(T));
 - }
 - List<T> list = new List<T>();
 - Dictionary<string, PropertyInfo> properties = propertyMappings[typeof(T)];
 - T t;
 - while (reader.Read())
 - {
 - t = new T();
 - foreach (KeyValuePair<string, PropertyInfo> item in properties)
 - {
 - //如果对应的属性名出现在数据源的列中则获取值并设置给对应的属性
 - if (reader[item.Key] != null)
 - {
 - item.Value.SetValue(t, GetValueFromObject(reader[item.Key], item.Value.PropertyType), null);
 - }
 - }
 - list.Add(t);
 - }
 - return list;
 - }
 - /// <summary>
 - /// 从DbDataReader的实例中读取简单数据类型(String,ValueType)
 - /// </summary>
 - /// <typeparam name="T">目标数据类型</typeparam>
 - /// <param name="reader">DbDataReader的实例</param>
 - /// <returns></returns>
 - private static List<T> GetSimpleEntities<T>(DbDataReader reader)
 - {
 - List<T> list = new List<T>();
 - while (reader.Read())
 - {
 - list.Add((T)GetValueFromObject(reader[0], typeof(T)));
 - }
 - return list;
 - }
 - /// <summary>
 - /// 将Object转换成字符串类型
 - /// </summary>
 - /// <param name="value">object类型的实例</param>
 - /// <returns></returns>
 - private static object GetString(object value)
 - {
 - return Convert.ToString(value);
 - }
 - /// <summary>
 - /// 将指定的 Object 的值转换为指定枚举类型的值。
 - /// </summary>
 - /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
 - /// <param name="targetType"></param>
 - /// <returns></returns>
 - private static object GetEnum(object value, Type targetType)
 - {
 - return Enum.Parse(targetType, value.ToString());
 - }
 - /// <summary>
 - /// 将指定的 Object 的值转换为指定枚举类型的值。
 - /// </summary>
 - /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
 - /// <returns></returns>
 - private static object GetBoolean(object value)
 - {
 - if (value is Boolean)
 - {
 - return value;
 - }
 - else
 - {
 - byte byteValue = (byte)GetByte(value);
 - if (byteValue == 0)
 - {
 - return false;
 - }
 - else
 - {
 - return true;
 - }
 - }
 - }
 - /// <summary>
 - /// 将指定的 Object 的值转换为指定枚举类型的值。
 - /// </summary>
 - /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
 - /// <returns></returns>
 - private static object GetByte(object value)
 - {
 - if (value is Byte)
 - {
 - return value;
 - }
 - else
 - {
 - return byte.Parse(value.ToString());
 - }
 - }
 - /// <summary>
 - /// 将指定的 Object 的值转换为指定枚举类型的值。
 - /// </summary>
 - /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
 - /// <returns></returns>
 - private static object GetSByte(object value)
 - {
 - if (value is SByte)
 - {
 - return value;
 - }
 - else
 - {
 - return SByte.Parse(value.ToString());
 - }
 - }
 - /// <summary>
 - /// 将指定的 Object 的值转换为指定枚举类型的值。
 - /// </summary>
 - /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
 - /// <returns></returns>
 - private static object GetChar(object value)
 - {
 - if (value is Char)
 - {
 - return value;
 - }
 - else
 - {
 - return Char.Parse(value.ToString());
 - }
 - }
 - /// <summary>
 - /// 将指定的 Object 的值转换为指定枚举类型的值。
 - /// </summary>
 - /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
 - /// <returns></returns>
 - private static object GetGuid(object value)
 - {
 - if (value is Guid)
 - {
 - return value;
 - }
 - else
 - {
 - return new Guid(value.ToString());
 - }
 - }
 - /// <summary>
 - /// 将指定的 Object 的值转换为指定枚举类型的值。
 - /// </summary>
 - /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
 - /// <returns></returns>
 - private static object GetInt16(object value)
 - {
 - if (value is Int16)
 - {
 - return value;
 - }
 - else
 - {
 - return Int16.Parse(value.ToString());
 - }
 - }
 - /// <summary>
 - /// 将指定的 Object 的值转换为指定枚举类型的值。
 - /// </summary>
 - /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
 - /// <returns></returns>
 - private static object GetUInt16(object value)
 - {
 - if (value is UInt16)
 - {
 - return value;
 - }
 - else
 - {
 - return UInt16.Parse(value.ToString());
 - }
 - }
 - /// <summary>
 - /// 将指定的 Object 的值转换为指定枚举类型的值。
 - /// </summary>
 - /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
 - /// <returns></returns>
 - private static object GetInt32(object value)
 - {
 - if (value is Int32)
 - {
 - return value;
 - }
 - else
 - {
 - return Int32.Parse(value.ToString());
 - }
 - }
 - /// <summary>
 - /// 将指定的 Object 的值转换为指定枚举类型的值。
 - /// </summary>
 - /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
 - /// <returns></returns>
 - private static object GetUInt32(object value)
 - {
 - if (value is UInt32)
 - {
 - return value;
 - }
 - else
 - {
 - return UInt32.Parse(value.ToString());
 - }
 - }
 - /// <summary>
 - /// 将指定的 Object 的值转换为指定枚举类型的值。
 - /// </summary>
 - /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
 - /// <returns></returns>
 - private static object GetInt64(object value)
 - {
 - if (value is Int64)
 - {
 - return value;
 - }
 - else
 - {
 - return Int64.Parse(value.ToString());
 - }
 - }
 - /// <summary>
 - /// 将指定的 Object 的值转换为指定枚举类型的值。
 - /// </summary>
 - /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
 - /// <returns></returns>
 - private static object GetUInt64(object value)
 - {
 - if (value is UInt64)
 - {
 - return value;
 - }
 - else
 - {
 - return UInt64.Parse(value.ToString());
 - }
 - }
 - /// <summary>
 - /// 将指定的 Object 的值转换为指定枚举类型的值。
 - /// </summary>
 - /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
 - /// <returns></returns>
 - private static object GetSingle(object value)
 - {
 - if (value is Single)
 - {
 - return value;
 - }
 - else
 - {
 - return Single.Parse(value.ToString());
 - }
 - }
 - /// <summary>
 - /// 将指定的 Object 的值转换为指定枚举类型的值。
 - /// </summary>
 - /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
 - /// <returns></returns>
 - private static object GetDouble(object value)
 - {
 - if (value is Double)
 - {
 - return value;
 - }
 - else
 - {
 - return Double.Parse(value.ToString());
 - }
 - }
 - /// <summary>
 - /// 将指定的 Object 的值转换为指定枚举类型的值。
 - /// </summary>
 - /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
 - /// <returns></returns>
 - private static object GetDecimal(object value)
 - {
 - if (value is Decimal)
 - {
 - return value;
 - }
 - else
 - {
 - return Decimal.Parse(value.ToString());
 - }
 - }
 - /// <summary>
 - /// 将指定的 Object 的值转换为指定枚举类型的值。
 - /// </summary>
 - /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
 - /// <returns></returns>
 - private static object GetDateTime(object value)
 - {
 - if (value is DateTime)
 - {
 - return value;
 - }
 - else
 - {
 - return DateTime.Parse(value.ToString());
 - }
 - }
 - /// <summary>
 - /// 将指定的 Object 的值转换为指定枚举类型的值。
 - /// </summary>
 - /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
 - /// <returns></returns>
 - private static object GetTimeSpan(object value)
 - {
 - if (value is TimeSpan)
 - {
 - return value;
 - }
 - else
 - {
 - return TimeSpan.Parse(value.ToString());
 - }
 - }
 - /// <summary>
 - /// 将指定的 Object 的值转换为指定枚举类型的值。
 - /// </summary>
 - /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
 - /// <returns></returns>
 - private static byte[] GetBinary(object value)
 - {
 - //如果该字段为NULL则返回null
 - if (value == DBNull.Value)
 - {
 - return null;
 - }
 - else if (value is Byte[])
 - {
 - return (byte[])(value);
 - }
 - else
 - {
 - return null;
 - }
 - }
 - /// <summary>
 - /// 将Object类型数据转换成对应的可空数值类型表示
 - /// </summary>
 - /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
 - /// <param name="targetType">可空数值类型</param>
 - /// <returns></returns>
 - private static object GetGenericValueFromObject(object value, Type targetType)
 - {
 - if (value == DBNull.Value)
 - {
 - return null;
 - }
 - else
 - {
 - //获取可空数值类型对应的基本数值类型,如int?->int,long?->long
 - //Type nonGenericType = genericTypeMappings[targetType];
 - Type nonGenericType = targetType.GetGenericArguments()[0];
 - return GetNonGenericValueFromObject(value, nonGenericType);
 - }
 - }
 - /// <summary>
 - /// 将指定的 Object 的值转换为指定类型的值。
 - /// </summary>
 - /// <param name="value">实现 IConvertible 接口的 Object,或者为 null</param>
 - /// <param name="targetType">目标对象的类型</param>
 - /// <returns></returns>
 - private static object GetNonGenericValueFromObject(object value, Type targetType)
 - {
 - if (targetType.IsEnum)//因为
 - {
 - return GetEnum(value, targetType);
 - }
 - else
 - {
 - switch (targetType.Name)
 - {
 - case "Byte": return GetByte(value);
 - case "SByte": return GetSByte(value);
 - case "Char": return GetChar(value);
 - case "Boolean": return GetBoolean(value);
 - case "Guid": return GetGuid(value);
 - case "Int16": return GetInt16(value);
 - case "UInt16": return GetUInt16(value);
 - case "Int32": return GetInt32(value);
 - case "UInt32": return GetUInt32(value);
 - case "Int64": return GetInt64(value);
 - case "UInt64": return GetUInt64(value);
 - case "Single": return GetSingle(value);
 - case "Double": return GetDouble(value);
 - case "Decimal": return GetDecimal(value);
 - case "DateTime": return GetDateTime(value);
 - case "TimeSpan": return GetTimeSpan(value);
 - default: return null;
 - }
 - }
 - }
 - /// <summary>
 - /// 获取该类型中属性与数据库字段的对应关系映射
 - /// </summary>
 - /// <param name="type"></param>
 - private static void GenerateTypePropertyMapping(Type type)
 - {
 - if (type != null)
 - {
 - PropertyInfo[] properties = type.GetProperties(BindingFlag);
 - Dictionary<string, PropertyInfo> propertyColumnMapping = new Dictionary<string, PropertyInfo>(properties.Length);
 - string description = string.Empty;
 - Attribute[] attibutes = null;
 - string columnName = string.Empty;
 - foreach (PropertyInfo p in properties)
 - {
 - columnName = string.Empty;
 - attibutes = Attribute.GetCustomAttributes(p);
 - foreach (Attribute attribute in attibutes)
 - {
 - //检查是否设置了ColumnName属性
 - if (attribute.GetType() == typeof(ColumnNameAttribute))
 - {
 - columnName = ((ColumnNameAttribute)attribute).ColumnName;
 - break;
 - }
 - }
 - //如果该属性是可读并且未被忽略的,则有可能在实例化该属性对应的类时用得上
 - if (p.CanWrite)
 - {
 - //如果没有设置ColumnName属性,则直接将该属性名作为数据库字段的映射
 - if (string.IsNullOrEmpty(columnName))
 - {
 - columnName = p.Name;
 - }
 - propertyColumnMapping.Add(columnName, p);
 - }
 - }
 - propertyMappings.Add(type, propertyColumnMapping);
 - }
 - }
 - }
 - /// <summary>
 - /// 自定义属性,用于指示如何从DataTable或者DbDataReader中读取类的属性值
 - /// </summary>
 - public class ColumnNameAttribute : Attribute
 - {
 - /// <summary>
 - /// 类属性对应的列名
 - /// </summary>
 - public string ColumnName { get; set; }
 - /// <summary>
 - /// 构造函数
 - /// </summary>
 - /// <param name="columnName">类属性对应的列名</param>
 - public ColumnNameAttribute(string columnName)
 - {
 - ColumnName = columnName;
 - }
 - }
 - }
 
注意:因为在machine.config中的<system.data> <DbProviderFactories>已经存在如下内容:
- <system.data>
 - <DbProviderFactories>
 - <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" />
 - <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" />
 - <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" />
 - <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" />
 - <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" />
 - </DbProviderFactories>
 - </system.data>
 
所以如果你采用以上的四种方式之一来访问数据,那么就不需要采取任何设置,但如果你是访问其它类型的数据库(如MySQL,SQLite)那么就需要在当前config文件的根节点下增加<system.data> <DbProviderFactories>节点,并在节点中增加你访问的数据库的方式,以下是可能值之一(注意并不是全部,添加时也不不必将下面的配置全部添加进去,只添加你所使用的数据库对应的方式即可):
- <add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" />
 - <add name="Informix Data Provider" invariant="IBM.Data.Informix" description=".Net Framework Data Provider for Informix" type="IBM.Data.Informix.IfxFactory, IBM.Data.Informix" />
 - <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" />
 - <add name="Firebird Data Provider" invariant="FirebirdSql.Data.FirebirdClient" description="Firebird" type="FirebirdSql.Data.FirebirdClient.FirebirdClientFactory, FirebirdSql.Data.FirebirdClient"/>
 - <add name="Oracle Data Provider" invariant="Oracle.DataAccess.Client" description=".Net Framework Data Provider for Oracle" type="Oracle.DataAccess.Client.OracleClientFactory, Oracle.DataAccess" />
 - <add name="PostgreSQL Data Provider Data Provider" invariant="Npgsql" description=".Net Framework Data Provider for PostgreSQL" type="Npgsql.NpgsqlFactory, Npgsql" />
 
比如在项目中使用了SQLite数据库,那么有关这部分的配置如下(这里讲述可能相当啰嗦,但也是没办法的事情,因为周公经常收到询问此处细节的留言):
- <?xml version="1.0" encoding="utf-8" ?>
 - <configuration>
 - <system.data>
 - <DbProviderFactories>
 - <add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" />
 - </DbProviderFactories>
 - </system.data>
 - </configuration>
 
C#通用数据访问类库的更多相关文章
- ClownFish:比手写代码还快的通用数据访问层
		
http://www.cnblogs.com/fish-li/archive/2012/07/17/ClownFish.html 阅读目录 开始 ClownFish是什么? 比手写代码还快的执行速度 ...
 - C# 通用数据访问类(SqlHelper)
		
[转]C# 通用数据访问类(SqlHelper) 注:本文转自http://www.tzwhx.com/newOperate/html/3/31/312/13080.htmlVisual C# 动态操 ...
 - ADO.NET笔记——使用通用数据访问
		
相关知识: 前面所有示例,君是访问特定的数据库(SQL Server),因此注入SqlConnection.SqlCommand.SqlDataReader.SqlDataAdapter等类名都添加了 ...
 - 基于Spring4+Hibernate4的通用数据访问层+业务逻辑层(Dao层+Service层)设计与实现!
		
基于泛型的依赖注入.当我们的项目中有很多的Model时,相应的Dao(DaoImpl),Service(ServiceImpl)也会增多. 而我们对这些Model的操作很多都是类似的,下面是我举出的一 ...
 - 自己写的Dapper通用数据访问层
		
using Microsoft.Practices.EnterpriseLibrary.Data; using Microsoft.Practices.EnterpriseLibrary.Data.O ...
 - 1.1 DAL数据访问层
		
分布式(Distributed)数据访问层(Data Access Layer),简称DAL,是利用MySQL Proxy.Memcached.集群等技术优点而构建的一个架构系统.主要目的是解决高并发 ...
 - 在 ASP.NET 中创建数据访问和业务逻辑层(转)
		
.NET Framework 4 当在 ASP.NET 中处理数据时,可从使用通用软件模式中受益.其中一种模式是将数据访问代码与控制数据访问或提供其他业务规则的业务逻辑代码分开.在此模式中,这两个层均 ...
 - 高性能JavaScript笔记一(加载和执行、数据访问、DOM编程)
		
写在前面 好的书,可能你第一遍并不能领会里面的精魂,当再次细细品评的时候,发现领悟的又是一层新的含义 (这段时间,工作上也不会像从前一样做起来毫不费力,开始有了新的挑战,现在的老大让我既佩服又嫉妒,但 ...
 - Winform开发框架之通用数据导入导出操作的事务性操作完善
		
1.通用数据导入导出操作模块回顾 在我的Winfrom开发框架里面,有一个通用的导入模块,它在默默处理这把规范的Excel数据导入到不同的对象表里面,一直用它来快速完成数据导入的工作.很早在随笔< ...
 
随机推荐
- DDMS介绍
			
DDMS全称:Dalvik Debug Monitor Service 一,DDMS的作用 它提供了截屏.查看线程和堆信息.logcat.进程.广播状态信息.模拟来电呼叫和短信.虚拟地理坐标等等. 二 ...
 - java IO 学习(二)
			
文件表示形式的转换: 一.从系统文件变成java中可以使用的文件对象 File file = new FIle("文件的路径"); 二.读取文件系统中文件的原始字节流,要读取字符流 ...
 - @Transactional、Spring的声明式事务
			
传送门 一.Spring的声明式事务 需要在xml文件中配置 <!--配置事务管理器类--> <bean id="transactionManager" clas ...
 - fff
			
https://qa.tutormeet.com/tutormeet/tutormeet_FF.html?lang=3&data=MjAxODAzMjcxODAwMTQ1OXwyNzQ2fGp ...
 - Oracle:"ORA-00942: 表或视图不存在"
			
情景 项目中使用Powerdesigner设计数据结构,在Powerdesigner中数据表和字段都区分了大小写,并生成了Oracle表,在执行Sql脚本时遇到以下问题:“ORA-00942: 表或视 ...
 - 洛谷九月月赛II
			
题解:模拟 一旦不匹配就要break #include<iostream> #include<cstdio> #include<cstring> #include& ...
 - ZeroClipboard.js兼容各种浏览器复制到剪切板上
			
http://www.cnblogs.com/huijieoo/articles/5569990.html <script type="text/javascript" sr ...
 - Docker中配置国内镜像
			
1. 为什么要为docker配置国内镜像 在正常情况下,docker有一个默认连接的国外官方镜像,在国外的网友访问该官方镜像自然不成问题,但是国内毕竟不是国外,由于国情不同,中国的网络访问国外官方 ...
 - 纯php实现中秋博饼游戏(1):绘制骰子图案
			
最近公司中秋博饼(在厦门),自己没事也想玩玩,所以就想动手写了一个纯php实现的中秋博饼游戏,既然要纯php实现,就要用php来生成图案,所以第一步就先绘制骰子图案. 平时很少使用php绘图,不过查查 ...
 - bzoj2875随机数生成器
			
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2875 矩阵乘裸题. 如果直接乘的话会爆long long,所以用加法代替乘,过程中不断取模. ...