C#操作SqlServer MySql Oracle通用帮助类(默认支持数据库读写分离、查询结果实体映射ORM)
【前言】
这篇文章将要介绍的主要内容如下:
1、ADO.NET之SqlServer
3、ADO.NET之MySql
【环境准备】
使用Nuget搜索 MySql.Data 引用即可:
2、Oracle连接器的DLL引用
在ADO.NET对SqlServer,Oracle,Mysql的操作熟练的基础上,我们逐渐发现所有的操作都是使用的同一套的东西,不同的是:
SqlServer的操作使用的是SqlConnection、SqlCommand,SqlDataAdapter;
MySql使用的是MySqlConnection、MySqlCommand、MySqlDataAdapter;
Oracle使用的是OracleSqlConnection、OracleCommand、OracleDataAdapter;
该连接类,操作类都分别继承自基础类:DbConnection、DbCommand、DbDataAdapter;
其类间关系如图所示:
1.DbConnection家族
2.DbCommand家族
3.DBDataAdapter家族
了解如上的几个特点后,我们里面能联系到了“多态”这个概念,我们可以使用同一套相同的代码,用“多态”的特性实例化出不同的实例,进而可以进一步封装我们的操作,达到代码精炼可重用的目的。
【实现过程】
1 public enum Opt_DataBaseType
2 {
3 SqlServer,
4 MySql,
5 Oracle
6 }
2.自定义内部类SqlConnection_WR_Safe(多态提供DbConnection的对象、读写分离的支持)
1 internal class DbCommandCommon : IDisposable
2 {
3 ///
4 /// common dbcommand
5 ///
6 public DbCommand DbCommand { get; set; }
7 public DbCommandCommon(Opt_DataBaseType dataBaseType)
8 {
9 this.DbCommand = GetDbCommand(dataBaseType);
10 }
11
12 ///
13 /// Get DbCommand select database type
14 ///
15 ///
16 ///
17 private DbCommand GetDbCommand(Opt_DataBaseType dataBaseType)
18 {
19 switch (dataBaseType)
20 {
21 case Opt_DataBaseType.SqlServer:
22 return new SqlCommand();
23 case Opt_DataBaseType.MySql:
24 return new MySqlCommand();
25 case Opt_DataBaseType.Oracle:
26 return new OracleCommand();
27 default:
28 return new SqlCommand();
29 }
30 }
31 ///
32 /// must dispose after use
33 ///
34 public void Dispose()
35 {
36 if (this.DbCommand != null)
37 {
38 this.DbCommand.Dispose();
39 }
40 }
41 }
4.自定义内部类 DbDataAdapterCommon 用于提供DbDataAdapter
>1 这里以ExecuteNonQuery为例:
1 public static int ExecuteNonQuery(string commandTextOrSpName, CommandType commandType = CommandType.Text) 2 { 3 using (SqlConnection_WR_Safe conn = new SqlConnection_WR_Safe(dataBaseType, ConnString_RW)) 4 { 5 using (DbCommandCommon cmd = new DbCommandCommon(dataBaseType)) 6 { 7 PreparCommand(conn.DbConnection, cmd.DbCommand, commandTextOrSpName, commandType); 8 return cmd.DbCommand.ExecuteNonQuery(); 9 } 10 } 11 }
该代码通过参数DataBaseType确定要实例化的数据库类型,ConnString_RW传入写数据库的连接字符串进行实例化,DbCommand也是使用dataBaseType实例我们需要实际操作的数据库对象。
>2 查询ExecuteDataSet方法:
该方法通过参数dataBaseType确定要实例化的具体DbConnection,通过读写分离的连接字符串进行选择读库和写库。
1 public static DataSet ExecuteDataSet(string commandTextOrSpName, CommandType commandType = CommandType.Text) 2 { 3 using (SqlConnection_WR_Safe conn = new SqlConnection_WR_Safe(dataBaseType, ConnString_R, ConnString_RW)) 4 { 5 using (DbCommandCommon cmd = new DbCommandCommon(dataBaseType)) 6 { 7 PreparCommand(conn.DbConnection, cmd.DbCommand, commandTextOrSpName, commandType); 8 using (DbDataAdapterCommon da = new DbDataAdapterCommon(dataBaseType, cmd.DbCommand)) 9 { 10 DataSet ds = new DataSet(); 11 da.Fill(ds); 12 return ds; 13 } 14 } 15 } 16 }
全部代码见此:
1 /*********************************************************
2 * CopyRight: QIXIAO CODE BUILDER.
3 * Version:4.2.0
4 * Author:qixiao(柒小)
5 * Create:2017-09-26 17:54:28
6 * Update:2017-09-26 17:54:28
7 * E-mail: dong@qixiao.me | wd8622088@foxmail.com
8 * GitHub: https://github.com/dong666
9 * Personal web site: http://qixiao.me
10 * Technical WebSit: http://www.cnblogs.com/qixiaoyizhan/
11 * Description:
12 * Thx , Best Regards ~
13 *********************************************************/
14 namespace QX_Frame.Bantina.Options
15 {
16 public enum Opt_DataBaseType
17 {
18 SqlServer,
19 MySql,
20 Oracle
21 }
22 }
2、主类代码Db_Helper_DG->
本类分为 ExecuteNonQuery、ExecuteScalar、ExecuteScalar、ExecuteDataTable、ExecuteDataSet、ExecuteList Entity、ExecuteEntity七大部分,每一部分分为 无条件参数执行Sql语句或存储过程、SqlParameter[]参数执行Sql语句,Object[]参数执行存储过程三个重载方法。
方法的详细代码见上一条主代码Db_Helper_DG中折叠部分,这里对ExecuteListEntity和ExecuteEntity方法进行着重介绍。
ExecuteListEntity和ExecuteEntity,此二方法是为了将查询结果和Model即Entity实体进行映射所用,使用C#反射Reflect技术,进行将查询结果直接赋值成为了Entity或者List
ExecuteList方法通过二次封装,显式调用GetListFromDataSet方法,从DataSet结果集中遍历结果以进行赋值,代码如下:
1 public static ListGetListFromDataSet (DataSet ds) where Entity : class 2 { 3 List list = new List ();//实例化一个list对象 4 PropertyInfo[] propertyInfos = typeof(Entity).GetProperties(); //获取T对象的所有公共属性 5 6 DataTable dt = ds.Tables[0]; // 获取到ds的dt 7 if (dt.Rows.Count > 0) 8 { 9 //判断读取的行是否>0 即数据库数据已被读取 10 foreach (DataRow row in dt.Rows) 11 { 12 Entity model1 = System.Activator.CreateInstance ();//实例化一个对象,便于往list里填充数据 13 foreach (PropertyInfo propertyInfo in propertyInfos) 14 { 15 try 16 { 17 //遍历模型里所有的字段 18 if (row[propertyInfo.Name] != System.DBNull.Value) 19 { 20 //判断值是否为空,如果空赋值为null见else 21 if (propertyInfo.PropertyType.IsGenericType && propertyInfo.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) 22 { 23 //如果convertsionType为nullable类,声明一个NullableConverter类,该类提供从Nullable类到基础基元类型的转换 24 NullableConverter nullableConverter = new NullableConverter(propertyInfo.PropertyType); 25 //将convertsionType转换为nullable对的基础基元类型 26 propertyInfo.SetValue(model1, Convert.ChangeType(row[propertyInfo.Name], nullableConverter.UnderlyingType), null); 27 } 28 else 29 { 30 propertyInfo.SetValue(model1, Convert.ChangeType(row[propertyInfo.Name], propertyInfo.PropertyType), null); 31 } 32 } 33 else 34 { 35 propertyInfo.SetValue(model1, null, null);//如果数据库的值为空,则赋值为null 36 } 37 } 38 catch (Exception) 39 { 40 propertyInfo.SetValue(model1, null, null);//如果数据库的值为空,则赋值为null 41 } 42 } 43 list.Add(model1);//将对象填充到list中 44 } 45 } 46 return list; 47 }
ExecuteEntity部分又分为从DataReader中获取和Linq从List
1 public static Entity GetEntityFromDataReader(DbDataReader reader) where Entity : class 2 { 3 Entity model = System.Activator.CreateInstance (); //实例化一个T类型对象 4 PropertyInfo[] propertyInfos = model.GetType().GetProperties(); //获取T对象的所有公共属性 5 using (reader) 6 { 7 if (reader.Read()) 8 { 9 foreach (PropertyInfo propertyInfo in propertyInfos) 10 { 11 //遍历模型里所有的字段 12 if (reader[propertyInfo.Name] != System.DBNull.Value) 13 { 14 //判断值是否为空,如果空赋值为null见else 15 if (propertyInfo.PropertyType.IsGenericType && propertyInfo.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) 16 { 17 //如果convertsionType为nullable类,声明一个NullableConverter类,该类提供从Nullable类到基础基元类型的转换 18 NullableConverter nullableConverter = new NullableConverter(propertyInfo.PropertyType); 19 //将convertsionType转换为nullable对的基础基元类型 20 propertyInfo.SetValue(model, Convert.ChangeType(reader[propertyInfo.Name], nullableConverter.UnderlyingType), null); 21 } 22 else 23 { 24 propertyInfo.SetValue(model, Convert.ChangeType(reader[propertyInfo.Name], propertyInfo.PropertyType), null); 25 } 26 } 27 else 28 { 29 propertyInfo.SetValue(model, null, null);//如果数据库的值为空,则赋值为null 30 } 31 } 32 return model;//返回T类型的赋值后的对象 model 33 } 34 } 35 return default(Entity);//返回引用类型和值类型的默认值0或null 36 }
1 public static Entity GetEntityFromDataSet(DataSet ds) where Entity : class 2 { 3 return GetListFromDataSet (ds).FirstOrDefault(); 4 }
【系统测试】
各种方式给Db_Helper_DG的链接字符串属性进行赋值,这里不再赘述。
根据测试表的设计进行新建对应的实体类:
1 public class TB_People 2 { 3 public Guid Uid { get; set; } 4 public string Name { get; set; } 5 public int Age { get; set; } 6 public int ClassId { get; set; } 7 }
填写好连接字符串,并给Db_Helper_DG类的ConnString_Default属性赋值后,我们直接调用方法进行查询操作。
调用静态方法ExecuteList以便直接映射到实体类:
1 ListpeopleList = Db_Helper_DG.ExecuteList ("select * from student where ClassId=?ClassId", System.Data.CommandType.Text, new MySqlParameter("?ClassId", 1)); 2 foreach (var item in peopleList) 3 { 4 Console.WriteLine(item.Name); 5 }
这里的MySql语句 select * from student where ClassId=?ClassId 然后参数化赋值 ?ClassId=1 进行查询。
结果如下:
可见,查询结果并无任何差池,自动映射到了实体类的属性。
2、SqlServer数据库操作
出处:https://www.cnblogs.com/7tiny/p/7602808.html