【Entity Framework】當Entity Framework 遇上 Oracle

當Entity Framework 遇上 Oracle

今年換工作,也從原本熟悉的MSSQL轉換到Oracle陣營。

雖然曾與Oracle小小的接觸過,但也僅僅知道參數是從【@】變成【:】的程度。

 

雖然,新的開發環境套用Entity Framework 5。

 

但,偶而還是會需要自行下Query Command。

就這麼遇到一個問題。

 

在Entity Framework情況下我有這麼一段:

var r = db.Database.SqlQuery<string>
        ("Select t0.PID from WEB_CONFIG t0 Where t0.PID = :p0 and t0.PANME = :p0",
         new OracleParameter("p0", "1")).ToList();


要注意一件事情:ODP.NET  OracleParameter預設是用Positon來做綁定。

簡單來說,就是靠參數的位置,而不是靠參數名稱來綁定數據的。

 

在Entity Framework 官網中:https://msdn.microsoft.com/zh-tw/library/system.data.entity.database.sqlquery%28v=vs.113%29.aspx

卻遍尋不著,改變這方法的途徑。

 

所以,如果真的想執行透過Paramter綁定數據,可以改為以下執行方式:

using(OracleCommand cmd = con.CreateCommand()) {
   ...
   cmd.BindByName = true;
   ...
}

來源擷取自網頁中。(http://stackoverflow.com/questions/1422032/oracle-ora-01008-not-all-variables-bound-error-w-parameters

 

但,這些都是我原本的問題引起的。
偶而,我們會有一些變數的值都是一樣的,在MSSQL的教育下,宣告成同一個Paramter是很正常的。就像最一開始那段Query。

今天,很自然的一樣這樣做,但,執行時卻會遇到ORA-1008的錯誤訊息。

 

出錯情境大致如下:

var sql = "Select t0.PID from WEB_CONFIG t0 Where t0.PID = :p0 and t0.Type = :p1 and t0.PANME = :p0";
var r = db.Database.SqlQuery<string>(sql, new OracleParameter("p0", "1"),new OracleParameter("p1", "2")).ToList();

注意一點:我們在兩個:p0中,多了一個:p1。

 

但,OracelPrameter還是只宣告p0 & p1。

此時就會報錯了!!

 

解決方法其實,轉換成【ODP.NET  OracleParameter預設是用Positon來做綁定】,這樣的想法,大概就會解了。

 

我的說法就是一個蘿蔔一個坑,的去宣告Parameter就對了。

所以,Stackoverflow也有說,雖然很蠢,但是,將程式碼改成:

var sql = "Select t0.PID from WEB_CONFIG t0 Where t0.PID = :p0 and t0.Type = :p1 and t0.PANME = :p0";
var r = db.Database.SqlQuery<string>(sql, new OracleParameter("p0", "1"),new OracleParameter("p1", "2"),new OracleParameter("p0", "2")).ToList();

這樣下去執行就對了。

雖然問題看似解決了,但其實我的觀念還沒真正清楚,看有無熱心人士可以為我解決了,或是自行找到再回來補充。

若我把程式改成:

var sql = "Select t0.PID from WEB_CONFIG t0 Where t0.Type = :p1 and t0.PID = :p0 and t0.PANME = :p0";
var r = db.Database.SqlQuery<string>(sql, new OracleParameter("p1", "2"),new OracleParameter("p0", "1")).ToList();

將順序改變一下,同時將一樣的p0都放在最後,OracleParamter p0也放在最後。

如此,程式碼還是正確執行。

這個道理何在?我至目前還是無解,期望可以找到正解。

結論,若要透過Entity Framework,目前最好採用一個蘿蔔一個坑方式。

否則,透過OracleCommand,同時將BindbyName設為true,也是不錯的方式。