C#操作SqlServer MySql Oracle通用帮助类

C#操作SqlServer MySql Oracle通用帮助类

【前言】

  作为一款成熟的面向对象高级编程语言,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 用于参数选择具体要实例的数据库

1 public enum Opt_DataBaseType
2 {
3         SqlServer,
4         MySql,
5         Oracle
6 }

  2.自定义内部类SqlConnection_WR_Safe(多态提供DbConnection的对象、读写分离的支持)

  1.在该内部类中,我们定义类属性DbConnection用于承接根据不同的数据库参数多态实例化后的对应Connection
  2.实现IDisposable接口,提供释放DbConnection的方法
  3.在读数据库连接失败时,及时切换到读写主数据库,提升系统的可用性

 1     internal class SqlConnection_WR_Safe : IDisposable
 2     {
 3         /// <summary>
 4         /// SqlConnection
 5         /// </summary>
 6         public DbConnection DbConnection { get; set; }
 7
 8         public SqlConnection_WR_Safe(Opt_DataBaseType dataBaseType, string ConnString_RW)
 9         {
10             this.DbConnection = GetDbConnection(dataBaseType, ConnString_RW);
11         }
12         /**
13          * if read db disabled,switchover to read write db immediately
14          * */
15         public SqlConnection_WR_Safe(Opt_DataBaseType dataBaseType, string ConnString_R, string ConnString_RW)
16         {
17             try
18             {
19                 this.DbConnection = GetDbConnection(dataBaseType, ConnString_R);
20             }
21             catch (Exception)
22             {
23                 this.DbConnection = GetDbConnection(dataBaseType, ConnString_RW);
24             }
25         }
26
27         /// <summary>
28         /// GetDataBase ConnectionString by database type and connection string -- private use
29         /// </summary>
30         /// <param name="dataBaseType"></param>
31         /// <param name="ConnString"></param>
32         /// <returns></returns>
33         private DbConnection GetDbConnection(Opt_DataBaseType dataBaseType, string ConnString)
34         {
35             switch (dataBaseType)
36             {
37                 case Opt_DataBaseType.SqlServer:
38                     return new SqlConnection(ConnString);
39                 case Opt_DataBaseType.MySql:
40                     return new MySqlConnection(ConnString);
41                 case Opt_DataBaseType.Oracle:
42                     return new OracleConnection(ConnString);
43                 default:
44                     return new SqlConnection(ConnString);
45             }
46         }
47         /// <summary>
48         /// Must Close Connection after use
49         /// </summary>
50         public void Dispose()
51         {
52             if (this.DbConnection != null)
53             {
54                 this.DbConnection.Dispose();
55             }
56         }
57     }

  3.自定义内部类 DbCommandCommon 用于提供DbCommand对象

 1     internal class DbCommandCommon : IDisposable
 2     {
 3         /// <summary>
 4         /// common dbcommand
 5         /// </summary>
 6         public DbCommand DbCommand { get; set; }
 7         public DbCommandCommon(Opt_DataBaseType dataBaseType)
 8         {
 9             this.DbCommand = GetDbCommand(dataBaseType);
10         }
11
12         /// <summary>
13         /// Get DbCommand select database type
14         /// </summary>
15         /// <param name="dataBaseType"></param>
16         /// <returns></returns>
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         /// <summary>
32         /// must dispose after use
33         /// </summary>
34         public void Dispose()
35         {
36             if (this.DbCommand != null)
37             {
38                 this.DbCommand.Dispose();
39             }
40         }
41     }

  4.自定义内部类 DbDataAdapterCommon 用于提供DbDataAdapter

  该类继承自DbDataAdapter,以实现DataAdapter的Fill方法,可以将结果集填充到DataSet中去。

 1     /// <summary>
 2     /// DbDataAdapterCommon
 3     /// </summary>
 4     internal class DbDataAdapterCommon : DbDataAdapter, IDisposable
 5     {
 6         public DbDataAdapter DbDataAdapter { get; set; }
 7         public DbDataAdapterCommon(Opt_DataBaseType dataBaseType, DbCommand dbCommand)
 8         {
 9             //get dbAdapter
10             this.DbDataAdapter = GetDbAdapter(dataBaseType, dbCommand);
11             //provid select command
12             this.SelectCommand = dbCommand;
13         }
14         private DbDataAdapter GetDbAdapter(Opt_DataBaseType dataBaseType, DbCommand dbCommand)
15         {
16             switch (dataBaseType)
17             {
18                 case Opt_DataBaseType.SqlServer:
19                     return new SqlDataAdapter();
20                 case Opt_DataBaseType.MySql:
21                     return new MySqlDataAdapter();
22                 case Opt_DataBaseType.Oracle:
23                     return new OracleDataAdapter();
24                 default:
25                     return new SqlDataAdapter();
26             }
27         }
28         /// <summary>
29         /// must dispose after use
30         /// </summary>
31         public new void Dispose()
32         {
33             if (this.DbDataAdapter != null)
34             {
35                 this.DbDataAdapter.Dispose();
36             }
37         }
38     }

  5.在执行Sql查询的时候,我们便使用我们自定义的内部类进行操作

  >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、数据库选择器枚举类:Opt_DataBaseType->

 

  2、主类代码Db_Helper_DG->

 Db_Helper_DG

  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<Entity>对象(此亦是ORM框架的核心)

  ExecuteList方法通过二次封装,显式调用GetListFromDataSet方法,从DataSet结果集中遍历结果以进行赋值,代码如下:

 1 public static List<Entity> GetListFromDataSet<Entity>(DataSet ds) where Entity : class
 2         {
 3             List<Entity> list = new List<Entity>();//实例化一个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<Entity>();//实例化一个对象,便于往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<Entity>获取第一条进行获取两种方式,由于DataReader有占用连接不释放的特点,在高并发的环境下使用并不友好,因此在实际生产环境中使用推荐使用第二种Linq获取List<Entity>的方式:

 1 public static Entity GetEntityFromDataReader<Entity>(DbDataReader reader) where Entity : class
 2         {
 3             Entity model = System.Activator.CreateInstance<Entity>();           //实例化一个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<Entity>(DataSet ds) where Entity : class
2         {
3             return GetListFromDataSet<Entity>(ds).FirstOrDefault();
4         }

【系统测试】

  在全部功能实现之余,下面我们进行代码测试环节。

  1、MySql数据库操作

  

  各种方式给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 List<TB_People> peopleList = Db_Helper_DG.ExecuteList<TB_People>("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数据库操作

  

  因为数据库结构MySql和SqlServer的结构是一致的,因此使用上述的实体类TB_People。

  

  同样填写连接字符串,并给Db_Helper_DG类的ConnString_Default属性赋值后,我们直接调用方法进行查询操作。

  

  

  然后我们修改Sql语句,并且修改为SqlServer传递参数方式进行查询:

   

1 List<TB_People> peopleList = Db_Helper_DG.ExecuteList<TB_People>("select * from TB_People where [email protected]", System.Data.CommandType.Text, new SqlParameter("@ClassId", 1));
2 foreach (var item in peopleList)
3 {
4     Console.WriteLine(item.Name);
5 }

  select * from TB_People where ClassId =1,ClassId按照SqlServer参数传递的方式进行传递。

  

  可见,查询结果并无任何差池,自动映射到了实体类的属性。

  3、Oracle由于本人当前Oracle环境问题,先不进行测试。

时间: 2024-10-10 03:47:54

C#操作SqlServer MySql Oracle通用帮助类的相关文章

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

Python操作sqlserver

一.使用模块介绍及安装 1.Python操作sqlserver所使用的模块是pymssql. 2.pymssql安装,直接使用pip install pymssql进行安装. 二.Python操作sqlserver介绍 1.数据库连接类及参数介绍 pymssql.connect:sqlserver连接的连接类. host(str):需要连接的数据库主机和实例.如:ip.ip\SQLEXPRESS..\SQLEXPRESS等. user(str):连接数据库的用户名.如:sa.test等. pas

SqlServer 、Oracle 、MySql 的区别

一.sqlserver 优点: 易用性.适合分布式组织的可伸缩性.用于决策支持的数据仓库功能.与许多其他服务器软件紧密关联的集成性.良好的性价比等: 为数据管理与分析带来了灵活性,允许单位在快速变化的环境中从容响应,从而获得竞争优势.从数据管理和分析角度看,将原始数据转化为商业智能和充分利用Web带来的机会非常重要.作为一个完备的数据库和数据分析包,SQLServer为快速开发新一代企业级商业应用程序.为企业赢得核心竞争优势打开了胜利之门.作为重要的基准测试可伸缩性和速度奖的记录保持者,SQLS

mysql、sqlserver、oracle三种数据库维护索引、外键、字段语法总结

mysql.sqlserver.oracle三种数据库维护索引.外键.字段语法总结 1.     MYSQL数据库 1)    创建索引 CREATE INDEX index_name ON table_name(column_list) CREATE UNIQUE INDEX index_name ON table_name(column_list) 修改表的方式添加索引 ALTER TABLE table_name ADD INDEX index_name(column_list) ALTE

hibernate4中oracle,sqlserver,mysql数据库的sql方言配置(SQL Dialects)

hibernate4中oracle,mysql,sqlserver数据库的sql方言配置(SQL Dialects) 数据库类型 Hibernate sql方言 DB2 org.hibernate.dialect.DB2Dialect DB2 AS/400 org.hibernate.dialect.DB2400Dialect DB2 OS390 org.hibernate.dialect.DB2390Dialect PostgreSQL 8.1 org.hibernate.dialect.Po

Mysql,SqlServer,Oracle主键自动增长的设置

1.把主键定义为自动增长标识符类型 MySql 在mysql中,如果把表的主键设为auto_increment类型,数据库就会自动为主键赋值.例如:   customers(id  auto_increment    , name (  customers(name)  id  customers; 以上sql语句先创建了customers表,然后插入两条记录,在插入时仅仅设定了name字段的值.最后查询表中id字段,查询结果为: 由此可见,一旦把id设为auto_increment类型,mys

php操作oracle的方法类集全

在网上开始找php中操作oracle的方法类~ 果然找到一个用php+oracle制作email表以及插入查询的教程,赶忙点开来看,从头到尾仔细的看了一遍,还没开始操作,便觉得收获很大了.地址在此:http://www.alixixi.com/program/a/2008050731615.shtml#replay. http://blog.163.com/[email protected]/blog/static/27712393201131815035122/        (博客校园) 摘

springmvc4 mybatis 整合 框架源码 bootstrap html5 mysql oracle sqlsever spring SSM

获取[下载地址]   QQ: 313596790   [免费支持更新] 三大数据库 mysql  oracle  sqlsever   更专业.更强悍.适合不同用户群体 [新录针对本系统的视频教程,手把手教开发一个模块,快速掌握本系统] A 集成代码生成器 [正反双向(单表.主表.明细表.树形表,开发利器)+快速构建表单; QQ:313596790 freemaker模版技术 ,0个代码不用写,生成完整的一个模块,带页面.建表sql脚本,处理类,service等完整模块 B 集成阿里巴巴数据库连

springmvc4 mybatis 整合 框架源码 bootstrap html5 mysql oracle sqlsever spring SSM SSH

获取[下载地址]   QQ: 313596790   [免费支持更新]三大数据库 mysql  oracle  sqlsever   更专业.更强悍.适合不同用户群体[新录针对本系统的视频教程,手把手教开发一个模块,快速掌握本系统] A 集成代码生成器 [正反双向(单表.主表.明细表.树形表,开发利器)+快速构建表单; QQ:313596790freemaker模版技术 ,0个代码不用写,生成完整的一个模块,带页面.建表sql脚本,处理类,service等完整模块B 集成阿里巴巴数据库连接池dr