C#操作SqlServer MySql Oracle通用帮助类Db_Helper_DG(默认支持数据库读写分离、查询结果实体映射ORM)
【前言】
作为一款成熟的面向对象高级编程语言,C#在ADO.Net的支持上已然是做的很成熟,我们可以方便地调用ADO.Net操作各类关系型数据库,在使用了多年的Sql_Helper_DG后,由于项目需要,于是乎,就准备写一个Mysql_Helper在实现过程中,发现ADO.Net封装之完善,以及面向对象的封装、继承、多态,有了这些特性,何不把数据库操作封装成为一个通用的类呢,此文由此铺展而来...
【实现功能】
这篇文章将要介绍的主要内容如下:
1、ADO.NET之SqlServer
2、ADO.NET之Oracle
3、ADO.NET之MySql
4、充分利用面向对象的特征,实现通用的操作类
【环境准备】
1、MySql连接器的DLL引用
使用Nuget搜索 MySql.Data 引用即可:
2、Oracle连接器的DLL引用
使用Nuget搜索 Oracle.ManagedDataAccess 进行引用:
【实现思路】
在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.定义枚举类 Opt_DataBaseType 用于参数选择具体要实例的数据库
public enum Opt_DataBaseType { SqlServer, MySql, Oracle }
2.自定义内部类SqlConnection_WR_Safe(多态提供DbConnection的对象、读写分离的支持)
1.在该内部类中,我们定义类属性DbConnection用于承接根据不同的数据库参数多态实例化后的对应Connection
2.实现IDisposable接口,提供释放DbConnection的方法
3.在读数据库连接失败时,及时切换到读写主数据库,提升系统的可用性
internal class SqlConnection_WR_Safe : IDisposable { /// <summary> /// SqlConnection /// </summary> public DbConnection DbConnection { get; set; } public SqlConnection_WR_Safe(Opt_DataBaseType dataBaseType, string ConnString_RW) { this.DbConnection = GetDbConnection(dataBaseType, ConnString_RW); } /** * if read db disabled,switchover to read write db immediately * */ public SqlConnection_WR_Safe(Opt_DataBaseType dataBaseType, string ConnString_R, string ConnString_RW) { try { this.DbConnection = GetDbConnection(dataBaseType, ConnString_R); } catch (Exception) { this.DbConnection = GetDbConnection(dataBaseType, ConnString_RW); } } /// <summary> /// GetDataBase ConnectionString by database type and connection string -- private use /// </summary> /// <param name="dataBaseType"></param> /// <param name="ConnString"></param> /// <returns></returns> private DbConnection GetDbConnection(Opt_DataBaseType dataBaseType, string ConnString) { switch (dataBaseType) { case Opt_DataBaseType.SqlServer: return new SqlConnection(ConnString); case Opt_DataBaseType.MySql: return new MySqlConnection(ConnString); case Opt_DataBaseType.Oracle: return new OracleConnection(ConnString); default: return new SqlConnection(ConnString); } } /// <summary> /// Must Close Connection after use /// </summary> public void Dispose() { if (this.DbConnection != null) { this.DbConnection.Dispose(); } } }
3.自定义内部类 DbCommandCommon 用于提供DbCommand对象
internal class DbCommandCommon : IDisposable { /// <summary> /// common dbcommand /// </summary> public DbCommand DbCommand { get; set; } public DbCommandCommon(Opt_DataBaseType dataBaseType) { this.DbCommand = GetDbCommand(dataBaseType); } /// <summary> /// Get DbCommand select database type /// </summary> /// <param name="dataBaseType"></param> /// <returns></returns> private DbCommand GetDbCommand(Opt_DataBaseType dataBaseType) { switch (dataBaseType) { case Opt_DataBaseType.SqlServer: return new SqlCommand(); case Opt_DataBaseType.MySql: return new MySqlCommand(); case Opt_DataBaseType.Oracle: return new OracleCommand(); default: return new SqlCommand(); } } /// <summary> /// must dispose after use /// </summary> public void Dispose() { if (this.DbCommand != null) { this.DbCommand.Dispose(); } } }
4.自定义内部类 DbDataAdapterCommon 用于提供DbDataAdapter
该类继承自DbDataAdapter,以实现DataAdapter的Fill方法,可以将结果集填充到DataSet中去。
/// <summary> /// DbDataAdapterCommon /// </summary> internal class DbDataAdapterCommon : DbDataAdapter, IDisposable { public DbDataAdapter DbDataAdapter { get; set; } public DbDataAdapterCommon(Opt_DataBaseType dataBaseType, DbCommand dbCommand) { //get dbAdapter this.DbDataAdapter = GetDbAdapter(dataBaseType, dbCommand); //provid select command this.SelectCommand = dbCommand; } private DbDataAdapter GetDbAdapter(Opt_DataBaseType dataBaseType, DbCommand dbCommand) { switch (dataBaseType) { case Opt_DataBaseType.SqlServer: return new SqlDataAdapter(); case Opt_DataBaseType.MySql: return new MySqlDataAdapter(); case Opt_DataBaseType.Oracle: return new OracleDataAdapter(); default: return new SqlDataAdapter(); } } /// <summary> /// must dispose after use /// </summary> public new void Dispose() { if (this.DbDataAdapter != null) { this.DbDataAdapter.Dispose(); } } }
5.在执行Sql查询的时候,我们便使用我们自定义的内部类进行操作
>1 这里以ExecuteNonQuery为例:
public static int ExecuteNonQuery(string commandTextOrSpName, CommandType commandType = CommandType.Text) { using (SqlConnection_WR_Safe conn = new SqlConnection_WR_Safe(dataBaseType, ConnString_RW)) { using (DbCommandCommon cmd = new DbCommandCommon(dataBaseType)) { PreparCommand(conn.DbConnection, cmd.DbCommand, commandTextOrSpName, commandType); return cmd.DbCommand.ExecuteNonQuery(); } } }
该代码通过参数DataBaseType确定要实例化的数据库类型,ConnString_RW传入写数据库的连接字符串进行实例化,DbCommand也是使用dataBaseType实例我们需要实际操作的数据库对象。
>2 查询ExecuteDataSet方法:
该方法通过参数dataBaseType确定要实例化的具体DbConnection,通过读写分离的连接字符串进行选择读库和写库。
public static DataSet ExecuteDataSet(string commandTextOrSpName, CommandType commandType = CommandType.Text) { using (SqlConnection_WR_Safe conn = new SqlConnection_WR_Safe(dataBaseType, ConnString_R, ConnString_RW)) { using (DbCommandCommon cmd = new DbCommandCommon(dataBaseType)) { PreparCommand(conn.DbConnection, cmd.DbCommand, commandTextOrSpName, commandType); using (DbDataAdapterCommon da = new DbDataAdapterCommon(dataBaseType, cmd.DbCommand)) { DataSet ds = new DataSet(); da.Fill(ds); return ds; } } } }
全部代码见此:
1、数据库选择器枚举类:Opt_DataBaseType->
/********************************************************* * CopyRight: QIXIAO CODE BUILDER. * Version:4.2.0 * Author:qixiao(柒小) * Create:2017-09-26 17:54:28 * Update:2017-09-26 17:54:28 * E-mail: dong@qixiao.me | wd8622088@foxmail.com * GitHub: https://github.com/dong666 * Personal web site: http://qixiao.me * Technical WebSit: http://www.cnblogs.com/qixiaoyizhan/ * Description: * Thx , Best Regards ~ *********************************************************/ namespace QX_Frame.Bantina.Options { public enum Opt_DataBaseType { SqlServer, MySql, Oracle } }
2、主类代码Db_Helper_DG->
/********************************************************* * CopyRight: QIXIAO CODE BUILDER. * Version:4.2.0 * Author:qixiao(柒小) * Create:2017-9-26 17:41:42 * Update:2017-9-26 17:41:42 * E-mail: dong@qixiao.me | wd8622088@foxmail.com * GitHub: https://github.com/dong666 * Personal web site: http://qixiao.me * Technical WebSit: http://www.cnblogs.com/qixiaoyizhan/ * Description: * Thx , Best Regards ~ *********************************************************/ using MySql.Data.MySqlClient; using Oracle.ManagedDataAccess.Client; using QX_Frame.Bantina.Options; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Data.Common; using System.Data.SqlClient; using System.Linq; using System.Reflection; namespace QX_Frame.Bantina { public abstract class Db_Helper_DG { #region ConnString 链接字符串声明 /// <summary> /// 连接字符串 ConnString_Default 默认,且赋值时会直接覆盖掉读写 /// </summary> private static string _connString = Configs.QX_Frame_Helper_DG_Config.ConnectionString_DB_QX_Frame_Default; public static string ConnString_Default { get { return _connString; } set { _connString = value; ConnString_RW = _connString; ConnString_R = _connString; } } /// <summary> /// 连接字符串 ConnString_RW 读写数据库使用 /// </summary> public static string ConnString_RW = _connString; /// <summary> /// 连接字符串 ConnString_R 读数据库使用 /// </summary> public static string ConnString_R = _connString; /// <summary> /// DataBaseType Select default:sqlserver /// </summary> public static Opt_DataBaseType dataBaseType = Configs.QX_Frame_Helper_DG_Config.DataBaseType; #endregion static Db_Helper_DG() { //if (string.IsNullOrEmpty(ConnString_RW) || string.IsNullOrEmpty(ConnString_R)) //{ // throw new ArgumentNullException("ConnString Can Not Be Null !"); //} } #region ExcuteNonQuery 执行sql语句或者存储过程,返回影响的行数---ExcuteNonQuery /// <summary> /// 执行sql语句或存储过程,返回受影响的行数,不带参数。 /// </summary> /// <param name="ConnString">连接字符串,可以自定义,可以以使用SqlHelper_DG.ConnString</param> /// <param name="commandTextOrSpName">sql语句或存储过程名称</param> /// <param name="commandType">命令类型 有默认值CommandType.Text</param> /// <returns>返回受影响的行数</returns> public static int ExecuteNonQuery(string commandTextOrSpName, CommandType commandType = CommandType.Text) { using (SqlConnection_WR_Safe conn = new SqlConnection_WR_Safe(dataBaseType, ConnString_RW)) { using (DbCommandCommon cmd = new DbCommandCommon(dataBaseType)) { PreparCommand(conn.DbConnection, cmd.DbCommand, commandTextOrSpName, commandType); return cmd.DbCommand.ExecuteNonQuery(); } } } /// <summary> /// 执行sql语句或存储过程,返回受影响的行数。 /// </summary> /// <param name="ConnString">连接字符串,可以自定义,可以以使用SqlHelper_DG.ConnString</param> /// <param name="commandTextOrSpName">sql语句或存储过程名称</param> /// <param name="commandType">命令类型 t</param> /// <param name="parms">SqlParameter[]参数数组,允许空</param> /// <returns>返回受影响的行数</returns> public static int ExecuteNonQuery(string commandTextOrSpName, CommandType commandType, params DbParameter[] parms) { using (SqlConnection_WR_Safe conn = new SqlConnection_WR_Safe(dataBaseType, ConnString_RW)) { using (DbCommandCommon cmd = new DbCommandCommon(dataBaseType)) { PreparCommand(conn.DbConnection, cmd.DbCommand, commandTextOrSpName, commandType, parms);//参数增加了commandType 可以自己编辑执行方式 return cmd.DbCommand.ExecuteNonQuery(); } } } /// <summary> /// 执行sql命令,返回受影响的行数。 /// </summary> /// <param name="ConnString">连接字符串,可以自定义,可以以使用SqlHelper_DG.ConnString</param> /// <param name="commandTextOrSpName">sql语句或存储过程名称</param> /// <param name="commandType">命令类型</param> /// <param name="obj">object[]参数数组,允许空</param> /// <returns>返回受影响的行数</returns> public static int ExecuteNonQuery(string commandTextOrSpName, CommandType commandType, params object[] obj) { using (SqlConnection_WR_Safe conn = new SqlConnection_WR_Safe(dataBaseType, ConnString_RW)) { using (DbCommandCommon cmd = new DbCommandCommon(dataBaseType)) { PreparCommand(conn.DbConnection, cmd.DbCommand, commandTextOrSpName, commandType, obj);//参数增加了commandType 可以自己编辑执行方式 return cmd.DbCommand.ExecuteNonQuery(); } } } #endregion #region ExecuteScalar 执行sql语句或者存储过程,执行单条语句,返回单个结果---ScalarExecuteScalar /// <summary> /// 执行sql语句或存储过程 返回ExecuteScalar (返回自增的ID)不带参数 /// </summary> /// <param name="ConnString">连接字符串,可以自定义,可以以使用SqlHelper_DG.ConnString</param> /// <param name="commandTextOrSpName">sql语句或存储过程名称</param> /// <param name="commandType">命令类型 有默认值CommandType.Text</param> /// <returns></returns> public static object ExecuteScalar(string commandTextOrSpName, CommandType commandType = CommandType.Text) { using (SqlConnection_WR_Safe conn = new SqlConnection_WR_Safe(dataBaseType, ConnString_R, ConnString_RW)) { using (DbCommandCommon cmd = new DbCommandCommon(dataBaseType)) { PreparCommand(conn.DbConnection, cmd.DbCommand, commandTextOrSpName, commandType); return cmd.DbCommand.ExecuteScalar(); } } } /// <summary> /// 执行sql语句或存储过程 返回ExecuteScalar (返回自增的ID) /// </summary> /// <param name="ConnString">连接字符串,可以自定义,可以以使用SqlHelper_DG.ConnString</param> /// <param name="commandTextOrSpName">sql语句或存储过程名称</param> /// <param name="commandType">命令类型</param> /// <param name="parms">SqlParameter[]参数数组,允许空</param> /// <returns></returns> public static object ExecuteScalar(string commandTextOrSpName, CommandType commandType, params DbParameter[] parms) { using (SqlConnection_WR_Safe conn = new SqlConnection_WR_Safe(dataBaseType, ConnString_R, ConnString_RW)) { using (DbCommandCommon cmd = new DbCommandCommon(dataBaseType)) { PreparCommand(conn.DbConnection, cmd.DbCommand, commandTextOrSpName, commandType, parms); return cmd.DbCommand.ExecuteScalar(); } } } /// <summary> /// 执行sql语句或存储过程 返回ExecuteScalar (返回自增的ID) /// </summary> /// <param name="ConnString">连接字符串,可以自定义,可以以使用SqlHelper_DG.ConnString</param> /// <param name="commandTextOrSpName">sql语句或存储过程名称</param> /// <param name="commandType">命令类型</param> /// <param name="obj">object[]参数数组,允许空</param> /// <returns></returns> public static object ExecuteScalar(string commandTextOrSpName, CommandType commandType, params object[] obj) { using (SqlConnection_WR_Safe conn = new SqlConnection_WR_Safe(dataBaseType, ConnString_R, ConnString_RW)) { using (DbCommandCommon cmd = new DbCommandCommon(dataBaseType)) { PreparCommand(conn.DbConnection, cmd.DbCommand, commandTextOrSpName, commandType, obj); return cmd.DbCommand.ExecuteScalar(); } } } #endregion #region ExecuteReader 执行sql语句或者存储过程,返回DataReader---DaataReader /// <summary> /// 执行sql语句或存储过程 返回DataReader 不带参数 /// </summary> /// <param name="ConnString">连接字符串,可以自定义,可以以使用SqlHelper_DG.ConnString</param> /// <param name="commandTextOrSpName">sql语句或存储过程名称</param> /// <param name="commandType">命令类型 有默认值CommandType.Text</param> /// <returns></returns> public static DbDataReader ExecuteReader(string commandTextOrSpName, CommandType commandType = CommandType.Text) { //sqlDataReader不能用using 会关闭conn 导致不能获取到返回值。注意:DataReader获取值时必须保持连接状态 SqlConnection_WR_Safe conn = new SqlConnection_WR_Safe(dataBaseType, ConnString_R, ConnString_RW); DbCommandCommon cmd = new DbCommandCommon(dataBaseType); PreparCommand(conn.DbConnection, cmd.DbCommand, commandTextOrSpName, commandType); return cmd.DbCommand.ExecuteReader(CommandBehavior.CloseConnection); } /// <summary> /// 执行sql语句或存储过程 返回DataReader /// </summary> /// <param name="ConnString">连接字符串,可以自定义,可以以使用SqlHelper_DG.ConnString</param> /// <param name="commandTextOrSpName">sql语句或存储过程名称</param> /// <param name="commandType">命令类型</param> /// <param name="parms">SqlParameter[]参数数组,允许空</param> /// <returns></returns> public static DbDataReader ExecuteReader(string commandTextOrSpName, CommandType commandType, params DbParameter[] parms) { //sqlDataReader不能用using 会关闭conn 导致不能获取到返回值。注意:DataReader获取值时必须保持连接状态 SqlConnection_WR_Safe conn = new SqlConnection_WR_Safe(dataBaseType, ConnString_R, ConnString_RW); DbCommandCommon cmd = new DbCommandCommon(dataBaseType); PreparCommand(conn.DbConnection, cmd.DbCommand, commandTextOrSpName, commandType, parms); return cmd.DbCommand.ExecuteReader(CommandBehavior.CloseConnection); } /// <summary> /// 执行sql语句或存储过程 返回DataReader /// </summary> /// <param name="ConnString">连接字符串,可以自定义,可以以使用SqlHelper_DG.ConnString</param> /// <param name="commandTextOrSpName">sql语句或存储过程名称</param> /// <param name="commandType">命令类型</param> /// <param name="obj">object[]参数数组,允许空</param> /// <returns></returns> public static DbDataReader ExecuteReader(string commandTextOrSpName, CommandType commandType, params object[] obj) { //sqlDataReader不能用using 会关闭conn 导致不能获取到返回值。注意:DataReader获取值时必须保持连接状态 SqlConnection_WR_Safe conn = new SqlConnection_WR_Safe(dataBaseType, ConnString_R, ConnString_RW); DbCommandCommon cmd = new DbCommandCommon(dataBaseType); PreparCommand(conn.DbConnection, cmd.DbCommand, commandTextOrSpName, commandType, obj); return cmd.DbCommand.ExecuteReader(CommandBehavior.CloseConnection); } #endregion #region ExecuteDataTable 执行sql语句或者存储过程,返回一个DataTable---DataTable /** * Update At 2017-3-2 14:58:45 * Add the ExecuteDataTable Method into Sql_Helper_DG **/ /// <summary> /// 执行sql语句或存储过程,返回DataTable不带参数 /// </summary> /// <param name="ConnString">连接字符串,可以自定义,可以以使用SqlHelper_DG.ConnString</param> /// <param name="commandTextOrSpName">sql语句或存储过程名称</param> /// <param name="commandType">命令类型 有默认值CommandType.Text</param> /// <returns></returns> public static DataTable ExecuteDataTable(string commandTextOrSpName, CommandType commandType = CommandType.Text) { using (SqlConnection_WR_Safe conn = new SqlConnection_WR_Safe(dataBaseType, ConnString_R, ConnString_RW)) { using (DbCommandCommon cmd = new DbCommandCommon(dataBaseType)) { PreparCommand(conn.DbConnection, cmd.DbCommand, commandTextOrSpName, commandType); using (DbDataAdapter da = new SqlDataAdapter(cmd.DbCommand as SqlCommand)) { DataSet ds = new DataSet(); da.Fill(ds); ) { ]; } return default(DataTable); } } } } /// <summary> /// 执行sql语句或存储过程,返回DataTable /// </summary> /// <param name="ConnString">连接字符串,可以自定义,可以以使用SqlHelper_DG.ConnString</param> /// <param name="commandTextOrSpName">sql语句或存储过程名称</param> /// <param name="commandType">命令类型</param> /// <param name="parms">SqlParameter[]参数数组,允许空</param> /// <returns></returns> public static DataTable ExecuteDataTable(string commandTextOrSpName, CommandType commandType, params DbParameter[] parms) { using (SqlConnection_WR_Safe conn = new SqlConnection_WR_Safe(dataBaseType, ConnString_R, ConnString_RW)) { using (DbCommandCommon cmd = new DbCommandCommon(dataBaseType)) { PreparCommand(conn.DbConnection, cmd.DbCommand, commandTextOrSpName, commandType, parms); using (DbDataAdapterCommon da = new DbDataAdapterCommon(dataBaseType, cmd.DbCommand)) { DataSet ds = new DataSet(); da.Fill(ds); ) { ]; } return default(DataTable); } } } } /// <summary> /// 执行sql语句或存储过程,返回DataTable /// </summary> /// <param name="ConnString">连接字符串,可以自定义,可以以使用SqlHelper_DG.ConnString</param> /// <param name="commandTextOrSpName">sql语句或存储过程名称</param> /// <param name="commandType">命令类型 </param> /// <param name="obj">object[]参数数组,允许空</param> /// <returns></returns> public static DataTable ExecuteDataTable(string commandTextOrSpName, CommandType commandType, params object[] obj) { using (SqlConnection_WR_Safe conn = new SqlConnection_WR_Safe(dataBaseType, ConnString_R, ConnString_RW)) { using (DbCommandCommon cmd = new DbCommandCommon(dataBaseType)) { PreparCommand(conn.DbConnection, cmd.DbCommand, commandTextOrSpName, commandType, obj); using (DbDataAdapterCommon da = new DbDataAdapterCommon(dataBaseType, cmd.DbCommand)) { DataSet ds = new DataSet(); da.Fill(ds); ) { ]; } return default(DataTable); } } } } #endregion #region ExecuteDataSet 执行sql语句或者存储过程,返回一个DataSet---DataSet /// <summary> /// 执行sql语句或存储过程,返回DataSet 不带参数 /// </summary> /// <param name="ConnString">连接字符串,可以自定义,可以以使用SqlHelper_DG.ConnString</param> /// <param name="commandTextOrSpName">sql语句或存储过程名称</param> /// <param name="commandType">命令类型 有默认值CommandType.Text</param> /// <returns></returns> public static DataSet ExecuteDataSet(string commandTextOrSpName, CommandType commandType = CommandType.Text) { using (SqlConnection_WR_Safe conn = new SqlConnection_WR_Safe(dataBaseType, ConnString_R, ConnString_RW)) { using (DbCommandCommon cmd = new DbCommandCommon(dataBaseType)) { PreparCommand(conn.DbConnection, cmd.DbCommand, commandTextOrSpName, commandType); using (DbDataAdapterCommon da = new DbDataAdapterCommon(dataBaseType, cmd.DbCommand)) { DataSet ds = new DataSet(); da.Fill(ds); return ds; } } } } /// <summary> /// 执行sql语句或存储过程,返回DataSet /// </summary> /// <param name="ConnString">连接字符串,可以自定义,可以以使用SqlHelper_DG.ConnString</param> /// <param name="commandTextOrSpName">sql语句或存储过程名称</param> /// <param name="commandType">命令类型</param> /// <param name="parms">SqlParameter[]参数数组,允许空</param> /// <returns></returns> public static DataSet ExecuteDataSet(string commandTextOrSpName, CommandType commandType, params DbParameter[] parms) { using (SqlConnection_WR_Safe conn = new SqlConnection_WR_Safe(dataBaseType, ConnString_R, ConnString_RW)) { using (DbCommandCommon cmd = new DbCommandCommon(dataBaseType)) { PreparCommand(conn.DbConnection, cmd.DbCommand, commandTextOrSpName, commandType, parms); using (DbDataAdapterCommon da = new DbDataAdapterCommon(dataBaseType, cmd.DbCommand)) { DataSet ds = new DataSet(); da.Fill(ds); return ds; } } } } /// <summary> /// 执行sql语句或存储过程,返回DataSet /// </summary> /// <param name="ConnString">连接字符串,可以自定义,可以以使用SqlHelper_DG.ConnString</param> /// <param name="commandTextOrSpName">sql语句或存储过程名称</param> /// <param name="commandType">命令类型 </param> /// <param name="obj">object[]参数数组,允许空</param> /// <returns></returns> public static DataSet ExecuteDataSet(string commandTextOrSpName, CommandType commandType, params object[] obj) { using (SqlConnection_WR_Safe conn = new SqlConnection_WR_Safe(dataBaseType, ConnString_R, ConnString_RW)) { using (DbCommandCommon cmd = new DbCommandCommon(dataBaseType)) { PreparCommand(conn.DbConnection, cmd.DbCommand, commandTextOrSpName, commandType, obj); using (DbDataAdapterCommon da = new DbDataAdapterCommon(dataBaseType, cmd.DbCommand)) { DataSet ds = new DataSet(); da.Fill(ds); return ds; } } } } #endregion #region ExecuteList 执行sql语句或者存储过程,返回一个List<T>---List<T> public static List<Entity> ExecuteList<Entity>(string commandTextOrSpName, CommandType commandType = CommandType.Text) where Entity : class { return GetListFromDataSet<Entity>(ExecuteDataSet(commandTextOrSpName, commandType)); } public static List<Entity> ExecuteList<Entity>(string commandTextOrSpName, CommandType commandType, params DbParameter[] parms) where Entity : class { return GetListFromDataSet<Entity>(ExecuteDataSet(commandTextOrSpName, commandType, parms)); } public static List<Entity> ExecuteList<Entity>(string commandTextOrSpName, CommandType commandType, params object[] obj) where Entity : class { return GetListFromDataSet<Entity>(ExecuteDataSet(commandTextOrSpName, commandType, obj)); } #endregion #region ExecuteEntity 执行sql语句或者存储过程,返回一个Entity---Entity public static Entity ExecuteEntity<Entity>(string commandTextOrSpName, CommandType commandType = CommandType.Text) where Entity : class { return GetEntityFromDataSet<Entity>(ExecuteDataSet(commandTextOrSpName, commandType)); } public static Entity ExecuteEntity<Entity>(string commandTextOrSpName, CommandType commandType, params DbParameter[] parms) where Entity : class { return GetEntityFromDataSet<Entity>(ExecuteDataSet(commandTextOrSpName, commandType, parms)); } public static Entity ExecuteEntity<Entity>(string commandTextOrSpName, CommandType commandType, params object[] obj) where Entity : class { return GetEntityFromDataSet<Entity>(ExecuteDataSet(commandTextOrSpName, commandType, obj)); } #endregion #region ---PreparCommand 构建一个通用的command对象供内部方法进行调用--- /// <summary> /// 不带参数的设置sqlcommand对象 /// </summary> /// <param name="conn">sqlconnection对象</param> /// <param name="cmd">sqlcommmand对象</param> /// <param name="commandTextOrSpName">sql语句或存储过程名称</param> /// <param name="commandType">语句的类型</param> private static void PreparCommand(DbConnection conn, DbCommand cmd, string commandTextOrSpName, CommandType commandType) { //打开连接 if (conn.State != ConnectionState.Open) { conn.Open(); } //设置SqlCommand对象的属性值 cmd.Connection = conn; cmd.CommandType = commandType; cmd.CommandText = commandTextOrSpName; cmd.CommandTimeout = ; } /// <summary> /// 设置一个等待执行的SqlCommand对象 /// </summary> /// <param name="conn">sqlconnection对象</param> /// <param name="cmd">sqlcommmand对象</param> /// <param name="commandTextOrSpName">sql语句或存储过程名称</param> /// <param name="commandType">语句的类型</param> /// <param name="parms">参数,sqlparameter类型,需要指出所有的参数名称</param> private static void PreparCommand(DbConnection conn, DbCommand cmd, string commandTextOrSpName, CommandType commandType, params SqlParameter[] parms) { //打开连接 if (conn.State != ConnectionState.Open) { conn.Open(); } //设置SqlCommand对象的属性值 cmd.Connection = conn; cmd.CommandType = commandType; cmd.CommandText = commandTextOrSpName; cmd.CommandTimeout = ; if (parms != null) { cmd.Parameters.Clear(); cmd.Parameters.AddRange(parms); } } /// <summary> /// PreparCommand方法,可变参数为object需要严格按照参数顺序传参 /// 之所以会用object参数方法是为了我们能更方便的调用存储过程,不必去关系存储过程参数名是什么,知道它的参数顺序就可以了 sqlparameter必须指定每一个参数名称 /// </summary> /// <param name="conn">sqlconnection对象</param> /// <param name="cmd">sqlcommmand对象</param> /// <param name="commandTextOrSpName">sql语句或存储过程名称</param> /// <param name="commandType">语句的类型</param> /// <param name="parms">参数,object类型,需要按顺序赋值</param> private static void PreparCommand(DbConnection conn, DbCommand cmd, string commandTextOrSpName, CommandType commandType, params object[] parms) { //打开连接 if (conn.State != ConnectionState.Open) { conn.Open(); } //设置SqlCommand对象的属性值 cmd.Connection = conn; cmd.CommandType = commandType; cmd.CommandText = commandTextOrSpName; cmd.CommandTimeout = ; cmd.Parameters.Clear(); if (parms != null) { cmd.Parameters.AddRange(parms); } } #endregion #region 通过Model反射返回结果集 Model为 Entity 泛型变量的真实类型---反射返回结果集 /// <summary> /// 反射返回一个List T 类型的结果集 /// </summary> /// <typeparam name="T">Model中对象类型</typeparam> /// <param name="ds">DataSet结果集</param> /// <returns></returns> public static List<Entity> GetListFromDataSet<Entity>(DataSet ds) where Entity : class { try { List<Entity> list = new List<Entity>();//实例化一个list对象 PropertyInfo[] propertyInfos = typeof(Entity).GetProperties(); //获取T对象的所有公共属性 DataTable dt = ds.Tables[]; // 获取到ds的dt ) { //判断读取的行是否>0 即数据库数据已被读取 foreach (DataRow row in dt.Rows) { Entity model1 = System.Activator.CreateInstance<Entity>();//实例化一个对象,便于往list里填充数据 foreach (PropertyInfo propertyInfo in propertyInfos) { try { //遍历模型里所有的字段 if (row[propertyInfo.Name] != System.DBNull.Value) { //判断值是否为空,如果空赋值为null见else if (propertyInfo.PropertyType.IsGenericType && propertyInfo.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) { //如果convertsionType为nullable类,声明一个NullableConverter类,该类提供从Nullable类到基础基元类型的转换 NullableConverter nullableConverter = new NullableConverter(propertyInfo.PropertyType); //将convertsionType转换为nullable对的基础基元类型 propertyInfo.SetValue(model1, Convert.ChangeType(row[propertyInfo.Name], nullableConverter.UnderlyingType), null); } else { propertyInfo.SetValue(model1, Convert.ChangeType(row[propertyInfo.Name], propertyInfo.PropertyType), null); } } else { propertyInfo.SetValue(model1, null, null);//如果数据库的值为空,则赋值为null } } catch (Exception) { propertyInfo.SetValue(model1, null, null);//如果数据库的值为空,则赋值为null } } list.Add(model1);//将对象填充到list中 } } return list; } catch (Exception ex) { throw ex; } } /// <summary> /// 反射返回一个T类型的结果 /// </summary> /// <typeparam name="T">Model中对象类型</typeparam> /// <param name="reader">SqlDataReader结果集</param> /// <returns></returns> public static Entity GetEntityFromDataReader<Entity>(DbDataReader reader) where Entity : class { try { Entity model = System.Activator.CreateInstance<Entity>(); //实例化一个T类型对象 PropertyInfo[] propertyInfos = model.GetType().GetProperties(); //获取T对象的所有公共属性 using (reader) { if (reader.Read()) { foreach (PropertyInfo propertyInfo in propertyInfos) { //遍历模型里所有的字段 if (reader[propertyInfo.Name] != System.DBNull.Value) { //判断值是否为空,如果空赋值为null见else if (propertyInfo.PropertyType.IsGenericType && propertyInfo.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) { //如果convertsionType为nullable类,声明一个NullableConverter类,该类提供从Nullable类到基础基元类型的转换 NullableConverter nullableConverter = new NullableConverter(propertyInfo.PropertyType); //将convertsionType转换为nullable对的基础基元类型 propertyInfo.SetValue(model, Convert.ChangeType(reader[propertyInfo.Name], nullableConverter.UnderlyingType), null); } else { propertyInfo.SetValue(model, Convert.ChangeType(reader[propertyInfo.Name], propertyInfo.PropertyType), null); } } else { propertyInfo.SetValue(model, null, null);//如果数据库的值为空,则赋值为null } } return model;//返回T类型的赋值后的对象 model } } return default(Entity);//返回引用类型和值类型的默认值0或null } catch (Exception ex) { throw ex; } } /// <summary> /// 反射返回一个T类型的结果 /// </summary> /// <typeparam name="T">Model中对象类型</typeparam> /// <param name="ds">DataSet结果集</param> /// <returns></returns> public static Entity GetEntityFromDataSet<Entity>(DataSet ds) where Entity : class { return GetListFromDataSet<Entity>(ds).FirstOrDefault(); } #endregion } /** * author:qixiao * time:2017-9-18 18:02:23 * description:safe create sqlconnection support * */ internal class SqlConnection_WR_Safe : IDisposable { /// <summary> /// SqlConnection /// </summary> public DbConnection DbConnection { get; set; } public SqlConnection_WR_Safe(Opt_DataBaseType dataBaseType, string ConnString_RW) { this.DbConnection = GetDbConnection(dataBaseType, ConnString_RW); } /** * if read db disabled,switchover to read write db immediately * */ public SqlConnection_WR_Safe(Opt_DataBaseType dataBaseType, string ConnString_R, string ConnString_RW) { try { this.DbConnection = GetDbConnection(dataBaseType, ConnString_R); } catch (Exception) { this.DbConnection = GetDbConnection(dataBaseType, ConnString_RW); } } /// <summary> /// GetDataBase ConnectionString by database type and connection string -- private use /// </summary> /// <param name="dataBaseType"></param> /// <param name="ConnString"></param> /// <returns></returns> private DbConnection GetDbConnection(Opt_DataBaseType dataBaseType, string ConnString) { switch (dataBaseType) { case Opt_DataBaseType.SqlServer: return new SqlConnection(ConnString); case Opt_DataBaseType.MySql: return new MySqlConnection(ConnString); case Opt_DataBaseType.Oracle: return new OracleConnection(ConnString); default: return new SqlConnection(ConnString); } } /// <summary> /// Must Close Connection after use /// </summary> public void Dispose() { if (this.DbConnection != null) { this.DbConnection.Dispose(); } } } /// <summary> /// Common sqlcommand /// </summary> internal class DbCommandCommon : IDisposable { /// <summary> /// common dbcommand /// </summary> public DbCommand DbCommand { get; set; } public DbCommandCommon(Opt_DataBaseType dataBaseType) { this.DbCommand = GetDbCommand(dataBaseType); } /// <summary> /// Get DbCommand select database type /// </summary> /// <param name="dataBaseType"></param> /// <returns></returns> private DbCommand GetDbCommand(Opt_DataBaseType dataBaseType) { switch (dataBaseType) { case Opt_DataBaseType.SqlServer: return new SqlCommand(); case Opt_DataBaseType.MySql: return new MySqlCommand(); case Opt_DataBaseType.Oracle: return new OracleCommand(); default: return new SqlCommand(); } } /// <summary> /// must dispose after use /// </summary> public void Dispose() { if (this.DbCommand != null) { this.DbCommand.Dispose(); } } } /// <summary> /// DbDataAdapterCommon /// </summary> internal class DbDataAdapterCommon : DbDataAdapter, IDisposable { public DbDataAdapter DbDataAdapter { get; set; } public DbDataAdapterCommon(Opt_DataBaseType dataBaseType, DbCommand dbCommand) { //get dbAdapter this.DbDataAdapter = GetDbAdapter(dataBaseType, dbCommand); //provid select command this.SelectCommand = dbCommand; } private DbDataAdapter GetDbAdapter(Opt_DataBaseType dataBaseType, DbCommand dbCommand) { switch (dataBaseType) { case Opt_DataBaseType.SqlServer: return new SqlDataAdapter(); case Opt_DataBaseType.MySql: return new MySqlDataAdapter(); case Opt_DataBaseType.Oracle: return new OracleDataAdapter(); default: return new SqlDataAdapter(); } } /// <summary> /// must dispose after use /// </summary> public new void Dispose() { if (this.DbDataAdapter != null) { this.DbDataAdapter.Dispose(); } } } }
Db_Helper_DG
Db_Helper_DG简介:
本类分为 ExecuteNonQuery、ExecuteScalar、ExecuteScalar、ExecuteDataTable、ExecuteDataSet、ExecuteList Entity、ExecuteEntity七大部分,每一部分分为 无条件参数执行Sql语句或存储过程、SqlParameter[]参数执行Sql语句,Object[]参数执行存储过程三个重载方法。
方法的详细代码见上一条主代码Db_Helper_DG中折叠部分,这里对ExecuteListEntity和ExecuteEntity方法进行介绍。
此二方法是为了将查询结果和Model即Entity实体进行映射所用,使用C#反射Reflect技术,进行将查询结果直接赋值成为了Entity或者List<Entity>对象(此亦是ORM框架的核心)
ExecuteList方法通过二次封装,显式调用GetListFromDataSet方法,从DataSet结果集中遍历结果以进行赋值,代码如下:
public static List<Entity> GetListFromDataSet<Entity>(DataSet ds) where Entity : class { List<Entity> list = new List<Entity>();//实例化一个list对象 PropertyInfo[] propertyInfos = typeof(Entity).GetProperties(); //获取T对象的所有公共属性 DataTable dt = ds.Tables[]; // 获取到ds的dt ) { //判断读取的行是否>0 即数据库数据已被读取 foreach (DataRow row in dt.Rows) { Entity model1 = System.Activator.CreateInstance<Entity>();//实例化一个对象,便于往list里填充数据 foreach (PropertyInfo propertyInfo in propertyInfos) { try { //遍历模型里所有的字段 if (row[propertyInfo.Name] != System.DBNull.Value) { //判断值是否为空,如果空赋值为null见else if (propertyInfo.PropertyType.IsGenericType && propertyInfo.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) { //如果convertsionType为nullable类,声明一个NullableConverter类,该类提供从Nullable类到基础基元类型的转换 NullableConverter nullableConverter = new NullableConverter(propertyInfo.PropertyType); //将convertsionType转换为nullable对的基础基元类型 propertyInfo.SetValue(model1, Convert.ChangeType(row[propertyInfo.Name], nullableConverter.UnderlyingType), null); } else { propertyInfo.SetValue(model1, Convert.ChangeType(row[propertyInfo.Name], propertyInfo.PropertyType), null); } } else { propertyInfo.SetValue(model1, null, null);//如果数据库的值为空,则赋值为null } } catch (Exception) { propertyInfo.SetValue(model1, null, null);//如果数据库的值为空,则赋值为null } } list.Add(model1);//将对象填充到list中 } } return list; }
ExecuteEntity部分又分为从DataReader中获取和Linq从List<Entity>获取第一条进行获取两种方式,由于DataReader有占用连接不释放的特点,在高并发的环境下使用并不友好,因此在实际生产环境中使用推荐使用第二种Linq获取List<Entity>的方式:
public static Entity GetEntityFromDataReader<Entity>(DbDataReader reader) where Entity : class { Entity model = System.Activator.CreateInstance<Entity>(); //实例化一个T类型对象 PropertyInfo[] propertyInfos = model.GetType().GetProperties(); //获取T对象的所有公共属性 using (reader) { if (reader.Read()) { foreach (PropertyInfo propertyInfo in propertyInfos) { //遍历模型里所有的字段 if (reader[propertyInfo.Name] != System.DBNull.Value) { //判断值是否为空,如果空赋值为null见else if (propertyInfo.PropertyType.IsGenericType && propertyInfo.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) { //如果convertsionType为nullable类,声明一个NullableConverter类,该类提供从Nullable类到基础基元类型的转换 NullableConverter nullableConverter = new NullableConverter(propertyInfo.PropertyType); //将convertsionType转换为nullable对的基础基元类型 propertyInfo.SetValue(model, Convert.ChangeType(reader[propertyInfo.Name], nullableConverter.UnderlyingType), null); } else { propertyInfo.SetValue(model, Convert.ChangeType(reader[propertyInfo.Name], propertyInfo.PropertyType), null); } } else { propertyInfo.SetValue(model, null, null);//如果数据库的值为空,则赋值为null } } return model;//返回T类型的赋值后的对象 model } } return default(Entity);//返回引用类型和值类型的默认值0或null }
public static Entity GetEntityFromDataSet<Entity>(DataSet ds) where Entity : class { return GetListFromDataSet<Entity>(ds).FirstOrDefault(); }
【系统测试】
在全部功能实现之余,下面我们进行代码测试环节。
1、MySql数据库操作
各种方式给Db_Helper_DG的链接字符串属性进行赋值,这里不再赘述。
根据测试表的设计进行新建对应的实体类:
public class TB_People { public Guid Uid { get; set; } public string Name { get; set; } public int Age { get; set; } public int ClassId { get; set; } }
填写好连接字符串,并给Db_Helper_DG类的ConnString_Default属性赋值后,我们直接调用方法进行查询操作。
调用静态方法ExecuteList以便直接映射到实体类:
List<TB_People> peopleList = Db_Helper_DG.ExecuteList<TB_People>()); foreach (var item in peopleList) { Console.WriteLine(item.Name); }
这里的MySql语句 select * from student where ClassId=?ClassId 然后参数化赋值 ?ClassId=1 进行查询。
结果如下:
可见,查询结果并无任何差池,自动映射到了实体类的属性。
至于,SqlServer就不再进行测试了吧,Oracle由于本人当前Oracle环境问题,先不进行测试。
C#操作SqlServer MySql Oracle通用帮助类Db_Helper_DG(默认支持数据库读写分离、查询结果实体映射ORM)的更多相关文章
- C#操作SqlServer MySql Oracle通用帮助类
C#操作SqlServer MySql Oracle通用帮助类 [前言] 作为一款成熟的面向对象高级编程语言,C#在ADO.Net的支持上已然是做的很成熟,我们可以方便地调用ADO.Net操作各类关系 ...
- centos MySQL主从配置 ntsysv chkconfig setup命令 配置MySQL 主从 子shell MySQL备份 kill命令 pid文件 discuz!论坛数据库读写分离 双主搭建 mysql.history 第二十九节课
centos MySQL主从配置 ntsysv chkconfig setup命令 配置MySQL 主从 子shell MySQL备份 kill命令 pid文件 discuz!论坛数 ...
- sqlserver,mysql,oracle通用的模拟和改进的全文搜索算法
问:数据库效率最低的地方是什么? 答:表扫描 问:表扫描常见的情况是 答:like '%a%' 这类查询 如果使用全文检索引擎,又无法满足我们的需求的时候怎么办,比如要从 一个商品名称 "农 ...
- Linux安装Mycat1.6.7.4并实现Mysql数据库读写分离简单配置
1. Mycat简介 一个彻底开源的,面向企业应用开发的大数据库集群 支持事务.ACID.可以替代MySQL的加强版数据库 一个可以视为MySQL集群的企业级数据库,用来替代昂贵的Oracle集群 一 ...
- MySQL中间件之ProxySQL_读写分离/查询重写配置
MySQL中间件之ProxySQL_读写分离/查询重写配置 Posted on 2016-12-25 by mark blue, mark Leave a comment MySQL 1.闲扯几句 读 ...
- 161220、使用Spring AOP实现MySQL数据库读写分离案例分析
一.前言 分布式环境下数据库的读写分离策略是解决数据库读写性能瓶颈的一个关键解决方案,更是最大限度了提高了应用中读取 (Read)数据的速度和并发量. 在进行数据库读写分离的时候,我们首先要进行数据库 ...
- ProxySQL+Mysql实现数据库读写分离实战
ProxySQL介绍 ProxySQL是一个高性能的MySQL中间件,拥有强大的规则引擎.具有以下特性:http://www.proxysql.com/ 1.连接池,而且是multiplexing 2 ...
- 170301、使用Spring AOP实现MySQL数据库读写分离案例分析
使用Spring AOP实现MySQL数据库读写分离案例分析 原创 2016-12-29 徐刘根 Java后端技术 一.前言 分布式环境下数据库的读写分离策略是解决数据库读写性能瓶颈的一个关键解决方案 ...
- 使用Spring AOP实现MySQL数据库读写分离案例分析
一.前言 分布式环境下数据库的读写分离策略是解决数据库读写性能瓶颈的一个关键解决方案,更是最大限度了提高了应用中读取 (Read)数据的速度和并发量. 在进行数据库读写分离的时候,我们首先要进行数据库 ...
随机推荐
- Android ViewPager无法使用wrap_content属性自适应高度
使用ViewPager的时候发现一个问题,当设置ViewPager控件的height属性为wrap_content时,控件高度一直是0,无法正常显示,在网上找到了解决办法,重写ViewPager的on ...
- 将指定目录中的txt文件转化成excel文件
#!/usr/bin/env python#coding:utf-8import reimport osimport globimport xlwtimport sysdir=r"F:\te ...
- python中列表 元组 字典 集合的区别
列表 元组 字典 集合的区别是python面试中最常见的一个问题.这个问题虽然很基础,但确实能反映出面试者的基础水平. (1)列表 什么是列表呢?我觉得列表就是我们日常生活中经常见到的清单.比如,统计 ...
- maven 搭新建成之后 无法创建 src/main/java 目录解决
maven项目创建后 创建 src/main/java 和 src/main/test 会报错,目录已存在 打开build path 界面 src/main/java 和 ...
- Java虚拟机基础
Java虚拟机基础 JVM是Java Virtual Machine的缩写.JVM是一个可以将Java字节码转换成机器语言并能被机器(电脑)执行的Java字节码处理引擎.Java字节码是处于Java和 ...
- 【pac4j】OAuth 认证机制 入门篇
1,pac4j是什么? pac4j是一个支持多种支持多种协议的身份认证的Java客户端. 2,pac4j的12种客户端认证机制:目前我只有用过第一和第八种. OAuth (1.0 & 2.0) ...
- angular2 官方demo heroApp
最近学习angular2,于是从官网的hero例子开始学习.经过几番周折终于完成了这个例子.收益匪浅.个人建议在开始学习例子前可以先了解一些概念,模块,组件,装饰器.....,有助于写代码时候的逻辑. ...
- 区块链下的io域名到底有多神秘?
不知大家发现没有 一些科技创业公司首选域名后缀 是.IO WHY? 因为给人一种很酷的感觉啊~ 譬如,极客届享誉盛名的盘古越狱团队官网:http://pangu.io 国内优质社区,简书--创作你的创 ...
- html加载和解析流程
之前查找资料了解了html的整个渲染过程,对于理解页面加载帮助还是蛮大的,下面我用visio把它画成流程图,便于直观理解 好吧,居然要150字才能发布............ 浏览器渲染过程 浏览器渲 ...
- 自制ACL+DHCP实验(初版)
(实验用gns模拟器) ACL 实验拓扑: 实验要求: 1.1.1.1→3.3.3.3 不通 11.11.11.11→3.3.3.3 通 2.2.2.2→3.3.3.3 通 实验步骤: 步骤一:基本配 ...