ODP.NET

風靈使發表於2019-02-16

1,什麼是ODP?就是Oracle 為 .NET (ODP.NET) 專門編寫了 Oracle Data Provider,一個用於 Microsoft .NET 環境下的 Oracle 資料訪問 API

詳細解說 http://www.oracle.com/technetwork/cn/testcontent/o23odp-084525-zhs.html

ODP.NET你不需要安裝Oracle,不需要配置oracle.key檔案,不需要配置TnsNames.Ora檔案 不需要配置環境變數;完全的傻瓜式的在沒有安裝oracle資料庫或者客戶端等任何oracle的產品的機器去訪問Oracle資料庫!

下面詳細解說ODP.NET如何對Oracle的資料操作【可以完成建表,CURD( 增刪查改)】

步驟一:獲取支援資料庫連線的類庫檔案:Oracle.DataAccess.dll 如何獲取呢?

到官網去相應的版本http://www.oracle.com/technetwork/cn/topics/dotnet/index-088718-zhs.html
要跑64位的.Net程式,就必須用64位的odp.net,要跑32位的.Net程式,就必須用32位的odp.net,最後給出odp.net32位與64位的下載地址:
64位下載地址
http://www.oracle.com/technetwork/database/windows/downloads/index-090165.html
32位下載地址
http://www.oracle.com/technetwork/database/windows/downloads/index-101290.html

在引用dll庫後,可能會引發下列異常:
在這裡插入圖片描述這就需要將專案的平臺改成相應的平臺即可:
在這裡插入圖片描述
步驟二:在正式使用之前,需要在專案中新增引用:

Oracle.DataAccess.Client 設定資料庫的連線等等通用功能,

Oracle.DataAccess.Types 設定 oracle自定義的一些資料型別

步驟三:例項解說

如提供以下資料庫的資訊

資料庫伺服器地址:192.168.10.20
庫名:44410g242
賬號:44bikll
密碼:487gf,.q

連線oracle的字串就是這樣的(提供我測試的2種方式)

//string conString = "Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.10.20)(PORT=1521))" +//"(CONNECT_DATA=(SERVER = DEDICATED)(SERVICE_NAME = 44410g242)));User Id=44bikll;Password=487gf,.q;"; 

string conString = "Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.10.20)(PORT=1521))" +"(CONNECT_DATA=(SID=44410g242)));User Id=44bikll;Password=487gf,.q;";  

//寫連線串以上2方法連線都可以,也可以放到Web.Config中。 

以上的連線協議TCP和埠1521都是預設的 ,無需修改,如埠被佔用了就需要改下。

本案例中涉及2個表TBLOCKLOGTBACCOUNT

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Oracle.DataAccess.Client;
using Oracle.DataAccess.Types;

namespace DHH_Bill_TBLockLog
{
    class Program
    {
        
        static void Main(string[] args)
        {
            #region 測試資料庫  
            Console.WriteLine("獲取testid031使用者在2013-4-11 15:53:40到2013-04-12 00:00:00的消費清單");
            Console.WriteLine();
            string conString = "Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.10.20)(PORT=1521))" +
              "(CONNECT_DATA=(SID=44410g242)));User Id=44bikll;Password=487gf,.q;"; //這個也可以放到Web.Config中。  
            
            //例項化OracleConnection物件 
            try
            {
                using (OracleConnection conn = new OracleConnection(conString))
                {
                    conn.Open();
                    string sql = "select TBACCOUNT.username,TBLOCKLOG.accountid,TBLOCKLOG.amount,TBLOCKLOG.locktime  FROM TBLOCKLOG,TBACCOUNT WHERE TBLOCKLOG.accountid=TBACCOUNT.accountid  ";
                    sql += " and TBLOCKLOG.serviceid=1 and TBACCOUNT.username='testid031' and TBLOCKLOG.status=1 and TBLOCKLOG.locktime >= to_date('2013-4-11 13:53:40','yyyy-mm-dd hh24:mi:ss') and TBLOCKLOG.locktime <= to_date('2013-04-12 00:00:00','yyyy-mm-dd hh24:mi:ss') order by TBLOCKLOG.locktime";
                    
                    using (OracleCommand comm = new OracleCommand(sql, conn))
                    {
                        
                        using (OracleDataReader rdr = comm.ExecuteReader())
                        {
                           
                            while (rdr.Read())
                            {
                                Console.WriteLine("UserName:" + rdr.GetString(0) + ",UserId:" + rdr.GetInt32(1) + ",點數:" + rdr.GetInt32(2) + "," + rdr.GetDateTime(3));

                            }
                           
                        }

                    }

                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            #endregion 

            Console.WriteLine(); Console.WriteLine();
            Console.WriteLine("計算2013-4-11 15:53:40到2013-04-12 00:00:00時間的testid031使用者消費的amount的總和");            
            Console.WriteLine(GetBillByDateAndGameId(conString, "testid031", 1, Convert.ToDateTime("2013-4-11 13:53:40"), Convert.ToDateTime("2013-04-12 00:00:00")));
           
        }



        public static int GetBillByDateAndGameId(string conString,string accountId, int gameId, DateTime beginTime, DateTime endTime)
        {
            try
            {
                using (OracleConnection conn = new OracleConnection(conString))
                {
                    accountId = accountId.ToLower();//全部轉換為小寫
                    conn.Open(); string sql = "select sum(TBLOCKLOG.amount) sumamount FROM TBLOCKLOG,TBACCOUNT WHERE TBLOCKLOG.accountid=TBACCOUNT.accountid  ";
                    sql += " and TBLOCKLOG.serviceid=" + gameId + " and TBACCOUNT.username='" + accountId + "' and TBLOCKLOG.status=1 and TBLOCKLOG.locktime >= to_date('" + beginTime + "','yyyy-mm-dd hh24:mi:ss') and TBLOCKLOG.locktime <= to_date('" + endTime + "','yyyy-mm-dd hh24:mi:ss') order by TBLOCKLOG.locktime";
                 
                    using (OracleCommand comm = new OracleCommand(sql, conn))
                    {

                        using (OracleDataReader rdr = comm.ExecuteReader())//建立一個OracleDateReader物件
                        {
                            int sum = 0;
                            while (rdr.Read())//讀取資料,如果odr.Read()返回為false的話,就說明到記錄集的尾部了
                            {
                                if (rdr.GetOracleValue(0).ToString() == "null")//防止為空 
                                {
                                    sum = 0;
                                }
                                else
                                {
                                    sum = int.Parse(rdr.GetOracleValue(0).ToString());
                                    //sum = int.Parse(rdr[0].ToString());
                                }
                               
                            }
                            return sum;
                        }

                    }

                }
            }
            catch (Exception ex)
            {
                return -1;
            }
        }
    }
}

顯示結果:
在這裡插入圖片描述
以下是:

1. 建立資料庫

建立一個名為OracleTypesTable的表

create table OracleTypesTable (MyVarchar2 varchar2(3000),MyNumber number(28,4) Primary key ,MyDate date,MyRaw RAW(255));

插入一行資料

insert into OracleTypesTable values ('test',4,to_date('2000-01-11 12:54:01','yyyy-mm-dd hh24:mi:ss'),'0001020304');

注意:

1,案例中的sql語句還是和mssql有一點區別的;

2,統計的話如果獲取不到統計的資料的會報錯,這就是我為什麼加上if (rdr.GetOracleValue(0).ToString() == "null")//防止為空

3,WebSERVICE的時候不知道為什麼他對使用者名稱的大小寫也有區分。

步驟四:部署說明

在部署到真實伺服器的時候,你也同樣按照步驟一中的步驟安裝客戶端ODP.NET檔案,點選執行EXE檔案自動配置環境變數,檢視一下是否安裝成功。

注意版本是否一致,這個是執行你的程式的關鍵,開啟cmd,執行:C:\Documents and Settings\Administrator>sqlplus /nolog 就可以知道版本

我的結果:
在這裡插入圖片描述


C#連線Oracle資料庫的方法(Oracle.DataAccess.Client也叫ODP.net)

官方下載地址(ODP.net)(中文):http://www.oracle.com/technetwork/cn/topics/dotnet/downloads/index.html

官方下載地址(ODP.net):http://www.oracle.com/technetwork/topics/dotnet/downloads/index.html

首先介紹下開發環境:WIn10 64bit+Visual Studio 2015+Oracle10ClientWin32(只是客戶端,如果安裝整個資料庫也是可以的)

目前瞭解C#中連線Oracle資料庫的方法有3種,分佈是微軟的System.Data.OracleClientOracle的Oracle.DataAccess.Client和Oracle的Oracle.ManagedDataAccess.dll(最優)

1.微軟的System.Data.OracleClient可以直接引用,但是VS會提示“System.Data.OracleClient.OracleConnection”已過時,這表明微軟自己都不建議使用了,所以知道就可以了,不必使用

2.C#使用Oracle.DataAccess.Client也叫ODP.net,他是Oracle提供的資料庫訪問類庫,其功能和效率上都有所保證,它還有一個非常方便特性:在客戶端上,可以不用安裝Oracle客戶端,直接拷貝即可使用。由於微軟在.net framework4中會將System.Data.OracleClient.dll deprecated,而且就訪問效率和速度而言,System.Data.OracleClient.dllOracle.DataAccess.dll相比,微軟的確實沒有oracle提供的類庫有優勢,所以我放棄了使用多年的System.Data.OracleClient.dll,取而代之的是odp.net。然而odp.net的優點不止這些,還包括:
1)不在安裝客戶端也能訪問伺服器上的oracle(假設Application ServerDB Server 分開)
2)不需要配置TnsNames.Ora檔案

具體的使用方法請參考這位大俠的 http://blog.csdn.net/rrrrssss00/article/details/7178515/

還有這位大俠的 http://blog.csdn.net/sumirry/article/details/46746331

如果專案要從System.Data.OracleClient.OracleConnectionOracle.DataAccess.Client時,只需要在oracle 安裝目錄下 找到 Oracle.DataAccess.dll新增引用,後 using Oracle.DataAccess.Client;
其他的都不用動,即可。
連線字串中 如有 用的是 user=xxx 就改成user id=xxx把原來 UsingSystem.Data.OracleClient去掉即可。

3.重點學習最後一種Oracle.ManagedDataAccess.dll,第二種的優點很多,但是也有缺點,就是要區分用區分x86/x64版本。

OracleConnection con = new OracleConnection(ConfigurationManager.ConnectionStrings["OracleConnString"].ToString());
            con.Open();
            OracleCommand cmd = new OracleCommand(cmdString, con);
            OracleDataAdapter oda = new OracleDataAdapter();
            oda.SelectCommand = cmd;
            oda.Fill(ds);
            GridView1.DataSource = ds;
            GridView1.DataBind();

Oracle ODP.NET資料庫訪問連線字串

Connection String Attribute 預設值 描述
Connection Lifetime 0 Maximum life time (in seconds) of the connection
當資料庫連線被返回到連線池中時,它的建立時間將與當前時間比較,如果超過了 Connection Lifetime 規定的時間,它將被釋放掉。 為 0 時將被視為最大連線時間。
Connection Timeout 15 Maximum time (in seconds) to wait for a free connection from the pool
Data Source empty string Oracle Net Service Name that identifies the database to connect to
DBA Privilege empty string Administrative privileges: SYSDBA or SYSOPER
Decr Pool Size 1 Controls the number of connections that are closed when an excessive amount of established connections are unused
Enlist True Enables or disables serviced components to automatically enlist in distributed transactions
當此值為 true 時,池中現存的所有資料庫連線將被加入到它的建立執行緒的 Transaction Context 中。如果不存在這個 Transaction Context 則無任何變化。
Incr Pool Size 5 Controls the number of connections that are established when all the connections in the pool are used
Max Pool Size 100 Maximum number of connections in a pool
Min Pool Size 1 Minimum number of connections in a pool
Password empty string Password for the user specified by User Id
Persist Security Info False Enables or disables the retrieval of password in the connection string
Pooling True Enables or disables connection pooling
Proxy User Id empty string User name of the proxy user
Proxy Password empty string Password of the proxy user
User Id empty string Oracle user name
...

OracleConnection con = new OracleConnection();

con.ConnectionString = "User Id=scott;Password=tiger;Data Source=oracle;Pooling=true;Enlist=true;Min Pool Size=10;Connection Lifetime=120;Connection Timeout=60;Incr Pool Size=5; Decr Pool Size=2";

con.Open();

...

以下網站提供連線字串大全:
www.ConnectionStrings.com


Oracle.ManagedDataAccess.dll全託管驅動學習總結

一、學習背景:

1)微軟自vs2010後放棄了自家的system.data.oracleClient驅動,推薦使用oracle提供的驅動。

2)微軟提供的system.data.oracleClient驅動存在oracle32位與64位連線相容性的問題,解決起來費時費力。

二、Oracle推薦的驅動:oracle.DataAccess.dlloracle.ManagedDataAccess.dll

1)oracle.DataAccess.dll的缺陷。oracle.DataAccess.dll需要幾個dll檔案,在實際使用中發現,oracle.DataAccess.dll無客戶端連線方式同樣存在所使用的dll檔案的32位與64位和oracle資料庫或系統本身存在的dll存在連線相容性問題。所以不推薦使用該驅動。

2)推薦使用oracle.ManagedDataAccess.dll(oracle.ManagedDataAccess.Client)全託管驅動。實際使用發現,oracle全託管驅動對32位和64位oracle資料庫具有很好的連線相容性。可採用無客戶端遠端連線oracle,或在本機使用連線。可通過visual studio 2010 nuget安裝,或直接下載dll檔案,然後引用oracle.ManagedDataAccess.dll檔案。在專案資料訪問層中引用名稱空間using oracle.ManagedDataAccess.Client,如圖2-1

圖 2-1引用oracle.ManagedDataAccess.Client名稱空間
在這裡插入圖片描述

三、Web.config連線字串

NET提供的連結字串connectionString="DataSource=192.168.1.2:1521/orcl;Persist Security Info=True;User ID=scott;Password=tiger";

四、關於command.BindByName = true;(重點敲黑板)

1)在使用全託管驅動oracle.ManagedDataAccess.dll後,ado.net的增刪查語句都執行正常,但是在執行修改語句(update語句)時,會引發異常。

2)預設情況下ODP.Net 繫結變數時,sql語句中的變數順序必須和變數繫結順序一致,否則Fill查不到資料,cmd.ExecuteNonQuery()返回0無法執行,將BindByName 設為true後,sql變數順序和繫結順序即可不一致