需求背景:某个模块需要远程访问Oracle数据库并进行操作,因为需要将之挂在若干服务器下运行,为了使实施人员更加方便快捷,要求做到不安装OracleClient,最好能做到不配置环境变量。
方案一:记录我最开始使用微软自带的 System.Data.OracleClient.dll 方法,踩了很多坑,所以先写一下,但是这个方案多了一个配置环境变量的步骤,可以直接跳过,浏览方案二
① 项目添加引用System.Data.OracleClient.dll
② 引入命名空间 using System.Data.OracleClient
③ 编写操作Oracle的帮助类(这里会有已弃用的警告,可以忽视)
④ 下载Instant Oracle http://www.oracle.com/technetwork/database/features/instant-client/index-097480.html
在这里下载所需的版本,只下载基础包即可(如 instantclient-basic-windows.x64-12.2.0.1.0.zip ),下载完成后解压备用。
⑤ 编译生成,将步骤④中解压好的oci.dll、orannzsbb10.dll、oraocci10.dll、oraociei10.dll 拷贝到项目编译生成的文件夹中(拿winform项目举例,即为.exe程序同级目录)
⑥ 配置环境变量 将步骤④中解压完毕的目录加入系统变量PATH中,为了确保System.Data.OracleClient能找到oci.dll。(如 D:\instantclient-basic-windows.x64-12.2.0.1.0)
⑦ 将debug文件夹拷贝到目标客户端运行。
此方案中值得注意的是
步骤③中,Oracle连接字符串格式 Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=服务器IP地址)(PORT=端口))(CONNECT_DATA=(SERVICE_NAME=服务器名称)));User Id=用户名;Password=密码;
步骤④中,下载时应注意后面的描述,里面说明了该安装包运行所需的环境(比如 Version 12.1.0.2.0:The 12.1 Basic package requires the Microsoft Visual Studio 2010 Redistributable.),否则无法识别dll,会报错:ORA-12541:TNS:无监听程序
步骤④中,下载的Instant Oracle版本一定要和项目生成的版本保持一致(如果项目生成为x86那么就要都保证是x86,AnyCPU则为x64)否则会报错 尝试加载Oracle客户端库时引发BadImageFomatException。如果在安装32位Oracle客户端组件的情况下以64位模式运行,将出现此问题。
方案二:使用Oracle官方驱动Oracle.ManagedDataAccess.dl,该方法方便快捷,不需要配置环境变量和客户端,而且该驱动还在维护,最重要的,无视操作系统位数问题。
① NuGet 或者 百度下载 Oracle.ManagedDataAccess.dl,项目中添加引用。
② 引入命名空间 using Oracle.ManagedDataAccess.Client (必要) ; using Oracle.ManagedDataAccess.Types;
③ 编写操作Oracle的帮助类(这里没有弃用警告)
④ 编译生成项目
⑤ 将debug文件夹拷贝到目标客户端运行。
此方案和方案一相比,只是少了很多不必要的步骤,数据库帮助类替换引用的命名空间后可以继续使用。
值得一提的是,方案二中使用的连接字符串和方案一不同,方案二中,连接字符串更简洁
Data Source=Ip/Database;User ID=uid;Password=pwd ,
例如 string conString = "Data Source=127.0.0.1:1521/mydb;User ID=zhzx;Password=123456";
public class DbHelperOracle : ISyncDbHelper
{
public string ConnectionString;
public DbHelperOracle(string connString)
{
this.ConnectionString = connString;
}
public IDataReader ExecuteReader(string SQLString)
{
OracleCommand cmd = new OracleCommand();
OracleConnection conn = new OracleConnection(ConnectionString);
try
{
PrepareCommand(cmd, conn, null, SQLString,null);
OracleDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
cmd.Parameters.Clear();
return reader;
}
catch
{
cmd.Dispose();
conn.Close();
throw;
}
}
public int ExecuteSql(string SQLString, object[] cmdParms)
{
OracleCommand cmd = new OracleCommand();
using (OracleConnection connection = new OracleConnection(ConnectionString))
{
connection.Open();
try
{
PrepareCommand(cmd, connection, null, SQLString, null);
int val = cmd.ExecuteNonQuery();
return val;
}
catch (Exception ex)
{
throw ex;
}
finally
{
connection.Close();
cmd.Parameters.Clear();
}
}
}
public DataSet Query(string SQLString)
{
using (OracleConnection connection = new OracleConnection(ConnectionString))
{
DataSet ds = new DataSet();
try
{
connection.Open();
OracleDataAdapter command = new OracleDataAdapter(SQLString, connection);
command.Fill(ds, "ds");
}
catch (OracleException ex)
{
throw new Exception(ex.Message);
}
finally
{
if (connection.State != ConnectionState.Closed)
{
connection.Close();
}
}
return ds;
}
}
public DataTable ExecuteDataTable(string sql, params OracleParameter[] parameters)
{
using (OracleConnection conn = new OracleConnection(ConnectionString))
{
conn.Open();
using (OracleCommand cmd = conn.CreateCommand())
{
cmd.CommandText = sql;
cmd.Parameters.AddRange(parameters);
OracleDataAdapter adapter = new OracleDataAdapter(cmd);
DataTable datatable = new DataTable();
adapter.Fill(datatable);
return datatable;
}
}
}
private static void PrepareCommand(OracleCommand cmd, OracleConnection conn, OracleTransaction trans, string cmdText, OracleParameter[] cmdParms)
{
if (conn.State != ConnectionState.Open)
conn.Open();
cmd.Connection = conn;
cmd.CommandText = cmdText;
if (trans != null)
cmd.Transaction = trans;
cmd.CommandType = CommandType.Text;//cmdType;
if (cmdParms != null)
{
foreach (OracleParameter parameter in cmdParms)
{
if ((parameter.Direction == ParameterDirection.InputOutput || parameter.Direction == ParameterDirection.Input) &&
(parameter.Value == null))
{
parameter.Value = DBNull.Value;
}
cmd.Parameters.Add(parameter);
}
}
}
}