使用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; ...
随机推荐
- oracle调用DLL
具体步骤:1.创建Oracle Library Create Library AAA as 'C:\UserData\xuxia\TestProc\Debug\TestProc.dll' 可以通 ...
- JAVA:当数据库重启后连接池没有自动识别的解决办法
今天发现服务器上的一个服务程序出现问题,软件抛出:Connection reset by peer: socket write error 无法正常提供服务,找了一下原因,原来是因为数据库服务器重启, ...
- MFC中运行出现问题“不支持尝试执行的操作”
http://blog.csdn.net/maturn/article/details/8051987 问题描述: 基于CDialogEx的对话框工程.VS2010开发环境. 调试运行到OnInitD ...
- DoubleOps.java
/****************************************************************************** * Compilation: javac ...
- bottle框架剖析
bottle框架剖析 使用 源码分析 一.使用 大致有以下几部分 quick start request routing generate contents request Data template ...
- ubuntu14.04上java jdk & mvn安装
这些常用工具的安装步骤还是自己记录下,以后再次用到时就会方便许多. 系统:ubuntu14.04 jdk安装. 1.从官网下载好jdk安装包 jdk-8u111-linux-x64.tar.gz 2. ...
- Telnet的三种登录方式
Telnet的三种登录方式 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.华为创建telnet的三种验证方式 首先,我们可以简单的看一个拓扑图,让我们可以在亦庄的路由器上对双桥 ...
- mysql -- 索引补充
.unique索引补充:联合唯一 unique(name,email)是name和email这两列联合起来唯一,不再试某个字段唯一 .主键索引,类似唯一索引,也是允许联合多个字段作为主键,例如:pri ...
- <!--more-->搭建的博客设置主页内容高度
用 markdown写文章时插入<!--more-->,文章会自动从插入的位置截断,也就是说在博客中只显示<!--more-->之前的内容,点击阅读全文之后会显示所有内容.
- mySQL数值类型的取值范围
如下图,int最大为2145483647,手机号码应该用bigint