一、使用OracleClient組件連接Oracle
.Net框架的System.Data.OracleClient.dll組件(ADO.Net組件),為連接和使用Oracle數據庫提供了很大的方便。
1、使用客戶端網絡服務名連接Oracle
基於業務邏輯與數據庫實體的分層需要,一般要求在不同於Oracle數據庫主機的客戶端機器連接和使用Oracle數據庫。這種情況要麼是通過C/S應用程序的客戶端訪問數據庫的情況;要麼是在B/S應用程序中,在WEB服務器端遠程連接Oracle數據庫服務器。
通過客戶端網絡服務名遠程連接Oracle,要求在客戶端機器中安裝Oracle客戶端工具(安裝類型可以不必選擇“管理員”模式,而只需要安裝運行時支持即可,為應用程序提供基本的網絡服務配置工具等)。
建立連接的語句比較簡單,關鍵點為data source的設置。這裡的data source不像SqlServer連接字串中指的是數據庫名稱,而是指客戶端網絡服務名(相關內容請參考前面有關客戶端安裝的文章)。對於本文的Oracle安裝來說,data source對應著E:\Oracle_Client\oracle\ora92\network\admin\tnsnames.ora配置文件中的網絡服務名(出於方便試驗的原因,數據庫與獨立的客戶端工具分別安裝在了同一台機器的不同目錄)。在具體實施連接時,將根據data
source的值去該客戶網絡服務配置文件中查找對應項,以獲取數據庫服務器主機地址、端口、全局數據庫名等連接信息。
建立連接的主要代碼如下:
......
using System.Data.OracleClient;
......
//這裡的“remotedb”對應於“Oracle客戶端的安裝與遠程連接配置”一文中配置的客戶端網絡服務名
OracleConnection conn=
new OracleConnection("data source=remotedb;User Id=scott;Password=scott;");
conn.Open();
......
2、本地連接和使用Oracle
本地使用Oracle是指在安裝Oracle數據庫的主機中連接和使用Oracle數據庫。從安全性和負載均衡的角度考慮,這種方式是不可取的。這裡僅作為實驗使用。
本地連接的代碼與遠程連接實際上沒有什麼分別,只不過其data source指向服務器端的客戶網絡服務名。對於本文的數據庫安裝,它指向E:\Oracle_Server\oracle\ora92\network\admin\tnsnames.ora文件中所定義的網絡服務名(有關內容請參考“Oracle客戶端的安裝與遠程連接配置”一文)。
對於這種本地連接方式,在服務器端不能存在獨立安裝的客戶端工具,否則data source只會去匹配獨立客戶端的tnsnames.ora文件,即使找不到對應的網絡服務名,也不會再去匹配服務器端的服務名。這不知是.Net組件的設計錯誤,還是故意為之,以鼓勵遠程連接和使用Oracle。
二、使用OleDB組件連接和訪問Oracle數據庫
OleDB組件是通過Oracle OleDB驅動程序(OraOLEDB.dll)連接和訪問Oracle數據庫,使用OleDB驅動的前提也是要在客戶端安裝運行時環境。可以采用自定義的客戶端安裝方式,安裝包括OraOLEDB.dll等在內的必須的文件,可以不必安裝包括配置客戶網絡服務等的客戶端工具。在這種情況下,OleDB的連接字串及簡單訪問數據庫的代碼如下所示:
......
using System.Data.OleDb;
......
//這裡的Data Source直接被賦值為類似tnsnames.ora文件中網絡服務名定義的內容,不再需要客戶端
//的配置文件tnsnames.ora(OracleClient也可以這樣處理)
OleDbConnection conn=
new OleDbConnection("Provider=OraOLEDB.Oracle.1;Server=localhost;
Data Source=(DESCRIPTION =(ADDRESS_LIST =(ADDRESS = (PROTOCOL = TCP)
(HOST = localhost)(PORT = 1521)))(CONNECT_DATA =(SERVICE_NAME = mydb.bawei)));
User ID=scott;Password=scott;");
conn.Open();
OleDbCommand comm=new OleDbCommand("select * from scott.emp",conn);
OleDbDataReader dr=comm.ExecuteReader();
Console.WriteLine("姓名 職位");
while(dr.Read())
{
Console.WriteLine(dr.GetString(1)+" "+dr.GetString(2));
}
Console.ReadLine();
dr.Close();
conn.Close();
......
使用OleDB組件可以獲得比OracleClient更高的效率和性能,因為OleDB是比ADO.NET更底層的組件,ADO.NET也要通過OleDB獲取數據。
三、一個使用Oracle存儲過程的簡單登錄驗證程序
1、創建用戶表
作為實驗用表,用戶表admin僅包含用戶名和密碼兩個字段。創建表的SQL語句如下:
CREATE TABLE SCOTT.ADMIN ("NAME" VARCHAR2(20) NOT NULL,
"PASSWORD" VARCHAR2(20) NOT NULL) TABLESPACE "EXAMPLE"
2、創建驗證用戶登錄的存儲過程
CREATE OR REPLACE PROCEDURE "SCOTT"."P_LOGIN" (v_Name varchar2,
v_Password varchar2,b_Passed out char) as
n_Count number;
begin
select count(*) into n_Count from admin where name=v_Name and password=v_Password;
if n_Count > 0 then
b_Passed:='1';
else
b_Passed:='0';
end if;
end;
3、在Sql Plus等sql工具中使用PL/SQL測試存儲過程是否可用:
set serveroutput on;
declare
v_Name varchar2(20);
v_password varchar(20);
b_Passed char(1);
begin
v_Name:='mxh';
v_Password:='mxh';
p_Login(v_Name,v_Password,b_Passed);
if b_Passed ='1' then
DBMS_OUTPUT.PUT_LINE('SUCCESS');
end if;
end;
4、創建一個登錄窗口,實驗C#對存儲過程的調用:
(1)編寫數據訪問類,用於訪問和操作數據庫:
//DataAccess.cs
using System;
using System.Data;
using System.Data.OracleClient;
namespace OraLoginProcedure
{
public class DataAccess
{
private string connStr="data source=yourdb;User Id=scott;Password=scott;";
private OracleConnection conn=null;
public DataAccess()
{
}
public DataAccess(string strConnection)
{
this.connStr=strConnection;
}
public OracleConnection getConnection()
{
try
{
if(conn==null)
conn=new OracleConnection(connStr);
if(conn.State==ConnectionState.Open)
conn.Open();
return conn;
}
catch(OracleException e)
{
throw e;
}
}
public void closeConnection()
{
if(conn.State==ConnectionState.Open)
conn.Close();
}
//執行存儲過程
public void RunProcedure(string storedProcName,OracleParameter[] parameters)
{
OracleCommand cmd=new OracleCommand(storedProcName,getConnection());
cmd.CommandType=CommandType.StoredProcedure;
foreach(OracleParameter parameter in parameters)
{
cmd.Parameters.Add(parameter);
}
cmd.ExecuteNonQuery();//執行存儲過程
closeConnection();
}
//執行登錄驗證(在實際應用中應該把這種執行業務邏輯的代碼與數據操作基礎代碼分離,以
//實現軟件的清晰分層、增強代碼的可復用性)
public bool Login(string username,string password)
{
OracleParameter[] parameters={
new OracleParameter("v_Name",OracleType.VarChar,20),
new OracleParameter("v_Password",OracleType.VarChar,20),
new OracleParameter("b_Passed",OracleType.Char,1)
};
parameters[0].Value=username;
parameters[1].Value=password;
parameters[0].Direction=ParameterDirection.Input;
parameters[1].Direction=ParameterDirection.Input;
parameters[2].Direction=ParameterDirection.Output;
try
{
RunProcedure("P_LOGIN",parameters);
if(parameters[2].Value.ToString() == "1")