使用ado.net打造通用的数据库操作类
最近在项目中使用中碰到了这样一种情况,查询的数据是从Oracle中获取的,但是记录下来的数据是存在Sql Server中(企业Oracle数据库管理太严,没办法操作)。而且我在之前的工作中也碰到过使用SQLite数据库,就借这次机会写一个通用的类库。
我在网上搜到了一篇利用工厂模式实现的通用类库,我在参考该文章基础上,做了一些修改。本文最好有一些Ado.net的基础。
感谢埋头前进的码农 https://www.cnblogs.com/lifeil/archive/2013/04/16/3024161.html的文章。
1.首先创建数据库的枚举类型
public enum DbProviderType : byte
{
// <summary>
/// 微软 SqlServer 数据库
/// </summary>
SqlServer, /// <summary>
/// 开源 MySql数据库
/// </summary>
MySql, /// <summary>
/// 嵌入式轻型数据库 SQLite
/// </summary>
SQLite, /// <summary>
/// 甲骨文 Oracle
/// </summary>
Oracle, /// <summary>
/// 旧版微软的oracle组件,目前已经废弃
/// </summary>
OracleClient, /// <summary>
/// 开放数据库互连
/// </summary>
ODBC, /// <summary>
/// 面向不同的数据源的低级应用程序接口
/// </summary>
OleDb, /// <summary>
/// 跨平台的关系数据库系统 Firebird
/// </summary>
Firebird, /// <summary>
///加州大学伯克利分校计算机系开发的关系型数据库 PostgreSql
/// </summary>
PostgreSql, /// <summary>
/// IBM出口的一系列关系型数据库管理系统 DB2
/// </summary>
DB2, /// <summary>
/// IBM公司出品的关系数据库管理系统(RDBMS)家族 Informix
/// </summary>
Informix, /// <summary>
/// 微软推出的一个适用于嵌入到移动应用的精简数据库产品 SqlServerCe
/// </summary>
SqlServerCe
}
2.创建好后,我们再设计一个ProviderFactory类,该类可以根据传过来的DbProviderType,创建不同的DbProviderFactory 对象,该对象用于一般的数据库操作。
public class ProviderFactory
{
/// <summary>
/// 保存每种数据访问方式对应的程序集名称
/// </summary>
private static Dictionary<MyHelper.Define.DbProviderType,string> providerInvariantNames =new Dictionary<MyHelper.Define.DbProviderType,string>(); /// <summary>
/// 保存已经生成的DbProviderFactory对象
/// </summary>
private readonly static Dictionary<MyHelper.Define.DbProviderType, DbProviderFactory> providerFactoies = new Dictionary<MyHelper.Define.DbProviderType, DbProviderFactory>(); /// <summary>
/// 加载已知的访问类型与名称
/// </summary>
static ProviderFactory()
{
providerInvariantNames.Add(MyHelper.Define.DbProviderType.SqlServer, "System.Data.SqlClient");
providerInvariantNames.Add(MyHelper.Define.DbProviderType.OleDb, "System.Data.OleDb");
providerInvariantNames.Add(MyHelper.Define.DbProviderType.ODBC, "System.Data.ODBC");
providerInvariantNames.Add(MyHelper.Define.DbProviderType.OracleClient, "System.Data.OracleClient");//已经废弃
providerInvariantNames.Add(MyHelper.Define.DbProviderType.Oracle, "Oracle.ManagedDataAccess.Client"); //需要安装Oracle.ManagedDataAccess插件,否则无效
providerInvariantNames.Add(MyHelper.Define.DbProviderType.MySql, "MySql.Data.MySqlClient");
providerInvariantNames.Add(MyHelper.Define.DbProviderType.SQLite, "System.Data.SQLite"); //注意在Nuget加入SQLite程序集
//出现错误的话,参考https://www.cnblogs.com/leleroyn/archive/2011/03/24/1993627.html
//<remove invariant="System.Data.SQLite"/>
//<add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" />
providerInvariantNames.Add(MyHelper.Define.DbProviderType.Firebird, "FirebirdSql.Data.Firebird");
providerInvariantNames.Add(MyHelper.Define.DbProviderType.PostgreSql, "Npgsql");
providerInvariantNames.Add(MyHelper.Define.DbProviderType.DB2, "IBM.Data.DB2.iSeries");
providerInvariantNames.Add(MyHelper.Define.DbProviderType.Informix, "IBM.Data.Informix");
providerInvariantNames.Add(MyHelper.Define.DbProviderType.SqlServerCe, "System.Data.SqlServerCe");
} public static DbProviderFactory GetDbProviderFactory(MyHelper.Define.DbProviderType providerType)
{
if (!providerFactoies.ContainsKey(providerType))
{
var factory = BuildDbProviderFactory(providerType); //生成DbProviderFactory对象
providerFactoies.Add(providerType, factory); //加入到字典中
}
return providerFactoies[providerType];
} /// <summary>
/// 生成DbProviderFactory对象
/// </summary>
/// <param name="providerType"></param>
/// <returns></returns>
private static DbProviderFactory BuildDbProviderFactory(MyHelper.Define.DbProviderType providerType)
{
string provideName = providerInvariantNames[providerType]; //程序集名称;
DbProviderFactory factory = null;
try
{
factory = DbProviderFactories.GetFactory(provideName);
}
catch (Exception ex)
{
factory = null;
}
return factory;
}
3.创建DbHelper类。
public class DbHelper
{
private DbProviderFactory _providerFactory;
private string _connectionString = null; //保存连接字符串 /// <summary>
/// 生成DbProviderFactory对象
/// </summary>
/// <param name="connectionString">连接字符串</param>
/// <param name="providerType">需要生成的DbProviderFactory对象</param>
public DbHelper(string connectionString,MyHelper.Define.DbProviderType providerType)
{
if (string.IsNullOrEmpty(connectionString)) //连接字符串不能为空
{
throw new ArgumentException("connectionString is not null");
}
_providerFactory = ProviderFactory.GetDbProviderFactory(providerType); //获取到生成的DbProviderFactory对象
_connectionString = connectionString;
if (_providerFactory == null)
{
throw new ArgumentException("can't build DbProviderFactory, please check DbProviderType ");
}
} /// <summary>
/// 判断数据库是否可以打开
/// </summary>
/// <returns></returns>
public bool CanOpen()
{
var dbConnection= _providerFactory.CreateConnection();
dbConnection.ConnectionString = _connectionString;
try
{
dbConnection.Open(); //打开连接
return true; }
catch (Exception ex)
{
return false;
}
finally
{
dbConnection.Close(); //关闭连接
}
} /// <summary>
///
/// </summary>
/// <returns></returns>
public DbConnection GetDbConnection()
{
var connection= _providerFactory.CreateConnection();
connection.ConnectionString = _connectionString;
return connection;
} /// <summary>
/// 执行增删改的方法
/// </summary>
/// <param name="sqlString">sql语句</param>
/// <param name="dbParameters">参数</param>
/// <param name="commandType">执行方式,是Sql语句还是存储过程</param>
/// <returns></returns>
public int ExecuteNonQuery(string sqlString ,DbParameter[] dbParameters,CommandType commandType)
{
int result;
using (DbConnection connection = GetDbConnection())
{
using (DbCommand command = CreateDbQueryCommand(connection, sqlString, dbParameters, commandType))
{
connection.Open();
result= command.ExecuteNonQuery();
connection.Close();
}
} return result;
} /// <summary>
/// 执行查询语句,返回DataSet
/// </summary>
/// <param name="sqlString"></param>
/// <param name="dbParameters"></param>
/// <param name="commandType"></param>
/// <returns></returns>
public DataSet ExecuteQuery(string sqlString, DbParameter[] dbParameters, CommandType commandType)
{
DataSet dataSet=new DataSet();
using (DbConnection connection = GetDbConnection())
{
using(DbDataAdapter adapter=_providerFactory.CreateDataAdapter())
{
adapter.SelectCommand=CreateDbQueryCommand(connection,sqlString,dbParameters,commandType);
connection.Open();
adapter.Fill(dataSet);
connection.Close();
}
}
return dataSet;
} private DbCommand CreateDbQueryCommand(DbConnection connection, string sqlString, IDbDataParameter[] dbParameters, CommandType commandType)
{
return CreateDbCommand(connection, sqlString, dbParameters, commandType, null);
} /// <summary>
/// 创建DbCommand对象
/// </summary>
/// <param name="connection">DbConnection对象</param>
/// <param name="sqlString">查询语句</param>
/// <param name="dbParameters">参数</param>
/// <param name="commandType">类型</param>
/// <param name="dbTransaction">事务</param>
/// <returns></returns>
public DbCommand CreateDbCommand(DbConnection connection, string sqlString, IDbDataParameter[] dbParameters, CommandType commandType,DbTransaction dbTransaction)
{
DbCommand command = _providerFactory.CreateCommand();
if (dbTransaction != null)
{
command.Transaction = dbTransaction;
}
command.CommandText = sqlString;
command.CommandType = commandType;
command.Connection = connection;
if (dbParameters != null)
{
command.Parameters.AddRange(dbParameters);
}
return command;
} /// <summary>
/// 返回第一行第一列的数据,一般用于执行聚合操作的语句
/// </summary>
/// <param name="sqlString">查询语句</param>
/// <param name="dbParameters">参数</param>
/// <param name="commandType">Sql语句还是存储过程</param>
/// <returns></returns>
public object ExecuteScalar(string sqlString, DbParameter[] dbParameters, CommandType commandType)
{
object result;
using (DbConnection connection = GetDbConnection())
{
using (DbCommand command = CreateDbQueryCommand(connection, sqlString, dbParameters, commandType))
{
connection.Open();
result = command.ExecuteScalar();
connection.Close();
}
}
return result;
}
方法的说明已经的很清楚了,有点Ado.net基础的同学应该都能看的懂。
下面进入我们的测试阶段,在这儿我们重点以Sql Server做测试,也会测试一下Oracle数据库和SQLite数据库。
首先我们创建一个TestDb的数据库,再创建一张Users表。

我们在创建一个存储过程,该存过过程根据传进来的ID值,返回Name字段。
下面是存储过程的代码:
Create procedure [dbo].[GetUser]
@id varchar(),
@name varchar() output
as
begin
select @name=name from Users where id=@id
end
现在开始测试。
首先我们先执行ExecuteQuery方法,该方法返回DataSet对象。
var connectionString = @"Server=.;Initial Catalog=TestDB;User ID=sa;Password=123456;";
DbHelper dbHelper = new DbHelper(connectionString, MyHelper.Define.DbProviderType.SqlServer);
string text = "select * from users "; var usersDataSet = dbHelper.ExecuteQuery(text, null, CommandType.Text); for (int i = ; i < usersDataSet.Tables[].Rows.Count; i++)
{
Console.WriteLine("ID:{0},名字:{1}", usersDataSet.Tables[].Rows[i][], usersDataSet.Tables[].Rows[i][]);
} Console.ReadKey();
结果:

执行ExecuteScalar方法,这儿我们查询出Users这张表的总数量。
var connectionString = @"Server=.;Initial Catalog=TestDB;User ID=sa;Password=123456;";
DbHelper dbHelper = new DbHelper(connectionString, MyHelper.Define.DbProviderType.SqlServer);
string text = "select count(*) from users "; var count = (int)dbHelper.ExecuteScalar(text, null, CommandType.Text);
Console.WriteLine("总数量:" + count.ToString()); Console.ReadKey();
结果

执行ExecuteNonQuery方法,在这儿我们执行带有返回参数的存储过程。
var connectionString = @"Server=.;Initial Catalog=TestDB;User ID=sa;Password=123456;";
DbHelper dbHelper = new DbHelper(connectionString, MyHelper.Define.DbProviderType.SqlServer);
string text = "GetUser ";
DbParameter[] parameters = new DbParameter[]
{
new SqlParameter("@id", SqlDbType.VarChar){ Value=""},
new SqlParameter("@name", SqlDbType.VarChar){ Direction=ParameterDirection.Output,Size=}
};
dbHelper.ExecuteNonQuery(text, parameters, CommandType.StoredProcedure);
Console.WriteLine("名字:" + parameters[].Value); Console.ReadKey();

上面的三种方法,我们都已经测试完成,没有任何问题。
下面我们来替换使用其他数据库继续测试。
Oracle数据库:
在测试前需要在Nuget中加入Oracle.ManagedDataAccess程序集,否则会出现错误。


var connectionString = @"Password=lisi;User ID=lisi;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.229.138)
(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=MLDN)))";
DbHelper dbHelper = new DbHelper(connectionString, MyHelper.Define.DbProviderType.Oracle);
string text = "select * from users "; var usersDataSet = dbHelper.ExecuteQuery(text, null, CommandType.Text); for (int i = ; i < usersDataSet.Tables[].Rows.Count; i++)
{
Console.WriteLine("ID:{0},名字:{1}", usersDataSet.Tables[].Rows[i][], usersDataSet.Tables[].Rows[i][]);
} Console.ReadKey();
结果

OK,Oracle也没问题。
下面试试看SQLite数据库。
该方法也需要在Nuget中加入SQLite的的插件:
如果不加入的话,会出现以下错误:


在装好后,不一定能使用起来,还是出现以上错误

则在Config文件DbProviderFactories节点中加入一段代码就可以了。
<remove invariant="System.Data.SQLite"/>
<add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" />

代码:
var connectionString = @"data source=mydb.db";
DbHelper dbHelper = new DbHelper(connectionString, MyHelper.Define.DbProviderType.SQLite); //string text = "create table users(id varchar(20),name varchar(20)); ";
//dbHelper.ExecuteNonQuery(text, null, CommandType.Text); //创建表 //string sql1 = "insert into users values('1','zhangsan')";
//string sql2 = "insert into users values('2','lisi')";
//dbHelper.ExecuteNonQuery(sql1, null, CommandType.Text); //创建表
//dbHelper.ExecuteNonQuery(sql2, null, CommandType.Text); //创建表 string selectSql = "select * from users";
var usersDataSet = dbHelper.ExecuteQuery(selectSql, null, CommandType.Text);
for (int i = ; i < usersDataSet.Tables[].Rows.Count; i++)
{
Console.WriteLine("ID:{0},名字:{1}", usersDataSet.Tables[].Rows[i][], usersDataSet.Tables[].Rows[i][]);
} Console.ReadKey();
在代码中我加入了创建表和插入数据的语句,该段代码被我注释了,如果想要测试的话,执行一次就可以了。

以上初步测试了SQL Server,Oracle和SQLite三种数据库。
参考文章:
https://www.cnblogs.com/leleroyn/archive/2011/03/24/1993627.html
https://www.cnblogs.com/gguozhenqian/p/4262813.html
https://www.cnblogs.com/lifeil/archive/2013/04/16/3024161.html
使用ado.net打造通用的数据库操作类的更多相关文章
- ADO.Net(三)——数据库操作类
操作数据类 避免代码重用.造对象太多.不能分工开发 利用面向对象的方法,把数据访问的方式优化一下,利用封装类 一般封装成三个类: 1.数据连接类 提供数据连接对象 需要引用命名空间: using Sy ...
- Android打造属于自己的数据库操作类。
1.概述 开发Android的同学都知道sdk已经为我们提供了一个SQLiteOpenHelper类来创建和管理SQLite数据库,通过写一个子类去继承它,就可以方便的创建.管理数据库.但是当我们需要 ...
- 通用数据库操作类,前端easyui-datagrid,form
实现功能: 左端datagrid显示简略信息,右侧显示选中行详细信息,数据库增删改 (1)点击选中行,右侧显示详细信息,其中[新增].[修改].[删除]按钮可用,[保存]按钮禁用 (2)点击[ ...
- C#全能数据库操作类及调用示例
C#全能数据库操作类及调用示例 using System; using System.Data; using System.Data.Common; using System.Configuratio ...
- 数据库操作类《SqlHelper》
一.背景 在看了一本书叫<Visual Studio 2010(C#)Windows数据库项目开发>后,觉得很多编程技术需要积累,因为一个简单的项目里包含的技术太多了,容易忘记.每次需要用 ...
- 【知识必备】ezSQL,最好用的数据库操作类,让php操作sql更简单~
最近用php做了点小东东,用上了ezSQL,感觉真的很ez,所以拿来跟大家分享一下~ ezSQL是一个非常好用的PHP数据库操作类.著名的开源博客WordPress的数据库操作就使用了ezSQL的My ...
- PHP 数据库操作类:ezSQL
EZSQL类介绍: 下载地址:http://www.jb51.net/codes/26393.htmlezsql是一个小型的快速的数据库操作类,可以让你很容易地用PHP操作各种数据库( MySQL.o ...
- php : mysql数据库操作类演示
设计目标: 1,该类一实例化,就可以自动连接上mysql数据库: 2,该类可以单独去设定要使用的连接编码(set names XXX) 3,该类可以单独去设定要使用的数据库(use XXX): 4,可 ...
- php MySQL数据库操作类源代码
php MySQL数据库操作类源代码: <?php class MySQL{ private $host; //服务器地址 private $name; //登录账号 private $pwd; ...
随机推荐
- 在Sqlite中通过Replace来实现插入和更新
你可能在批量处理一个事务的时候,想要批量插入一系列的数据,但是这些数据当添加完一次之后,重新添加的时候,你不想要重新添加,只是想将原有的数据进行更新,例如:我想要通过Excel将一系列的图书导入到 ...
- centos7配置本地yum源 使用安装镜像安装软件
1. 在cdrom挂载安装镜像.(物理机则插入光盘,虚拟机则在CD/DVD中选择iso镜像.如果虚拟机mount时提示找不到则在选择iso镜像上方勾选“已连接”和“启动时连接”,或者点击 虚拟机下方状 ...
- [luogu2114][起床困难综合症]
luogu2114 思路 因为位运算对于每一位是独立的,所以对每一位都对这n个数进行操作,然后观察最后得出的是1还是0.并且保证每一位拼起来之后要比m小. 代码 #include<cstdio& ...
- maven项目检出后报错(包括编译报错和运行报错)的常见检查处理方式
maven项目检出后报错(包括编译报错和运行报错)的常见检查处理方式: 1.更改项目的jdk为我们安装的jdk2.更改build配置里的 output folder 目录为 xxx项目名/target ...
- linux command ------ find
find | grep luoluo 将当前目录及子目录的文件名中含有luoluo的文件过滤出来 | 是管道,把find查找的内容传递给下个命令(grep) find后面不加其他内容(比如路径)表示打 ...
- MUI 样式按钮的禁用
1)如果是button,input等标签,可以 .attr("disabled",true)或者.attr("disabled","disab ...
- golang变量声明
func main() { var a1 int a1 = 1 var a = 1 b := 1 var c, d int c = 1 d = 1 var e, f = 1, 2 g, h := 1, ...
- Java编程思想 学习笔记1
一.对象导论 1.抽象过程 Alan Kay曾经总结了第一个成功的面向对象语言.同时也是Java所基于的语言之一的Smalltalk的五个基本特性,这些特性表现了纯粹的面向对象程序设计方式 1)万物皆 ...
- SQL语句(五)数据的修改
数据的修改 UPDATE 格式 UPDATE 表名 SET 字段名 = 字段值(这个可以是表达式) [WHERE 条件表达式] 关系运算符 (>.<.>=. <=.=.< ...
- 从匿名函数(闭包特性)到 PHP 设计模式之容器模式
匿名函数(匿名函数) 匿名函数,也叫闭包函数,它允许临时创建一个没有指定名称的函数,常用作回调函数参数的值,也可以作为变量的值来使用.具体的使用见以下示例代码: /* 示例一:声明一个简单匿名函数,并 ...