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三个类的相关代码如下:

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

其中EntityReader、ColumnNameAttribute的代码如下:

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

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

[html]   view plain copy
  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 plain copy
  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 plain copy
    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>  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
C#中,可以使用TcpClient类、Socket类等自带的类库来实现TCP客户端通信,也可以使用第三方类库,比如SuperSocket、DotNetty等。以下是使用TcpClient类实现TCP客户端通信的示例代码: ```csharp using System; using System.Net.Sockets; using System.Text; public class TcpClientExample { public static void Main() { try { // 创建TcpClient对象并连接服务器 TcpClient client = new TcpClient("服务器IP地址", 端口号); Console.WriteLine("连接成功!"); // 获取网络流对象 NetworkStream stream = client.GetStream(); // 发送消息 string message = "Hello server!"; byte[] data = Encoding.UTF8.GetBytes(message); stream.Write(data, 0, data.Length); Console.WriteLine("发送消息:{0}", message); // 接收消息 byte[] buffer = new byte[1024]; int length = stream.Read(buffer, 0, buffer.Length); string receivedMessage = Encoding.UTF8.GetString(buffer, 0, length); Console.WriteLine("收到消息:{0}", receivedMessage); // 关闭连接 stream.Close(); client.Close(); } catch (Exception ex) { Console.WriteLine(ex.Message); } } } ``` 在使用TcpClient类实现TCP客户端通信时,需要注意以下几点: 1. 使用TcpClient类进行连接时,如果连接失败,会抛出SocketException异常,需要进行异常处理。 2. 获取网络流对象时,需要使用TcpClient对象的GetStream()方法。 3. 发送消息时,需要将字符串转换为字节数组,可以使用Encoding.UTF8.GetBytes()方法进行转换。 4. 接收消息时,需要先定义一个字节数组作为缓冲区,然后使用网络流对象的Read()方法读取数据,并将读取到的数据存储在缓冲区中,最后将缓冲区中的数据转换为字符串。 5. 关闭连接时,需要先关闭网络流对象,再关闭TcpClient对象。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

微笑点燃希望

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值