PostgreSQL的.NET驅動程式Npgsql中參數對象的一個Bug

來源:互聯網
上載者:User

最近將公司的項目從SqlServer移植到PostgreSQL資料庫上來,在調用資料庫的預存程序(自訂函數)的時候,發現一個奇怪的問題,老是報函數無法找到。

先看一個PgSQL預存程序:

 

CREATE OR REPLACE FUNCTION updateattention(dm citext)
  RETURNS void AS
$BODY$
DECLARE
  
BEGIN
  update ZB set gzd=COALESCE(gzd,0)+1 where ZB.dm=$1 ;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION updateattention(citext) OWNER TO postgres;

在PostgreSQL中,函數和預存程序沒有區別,這裡我們把沒有傳回值的函數叫做預存程序吧,也許表訴的不太準確,還望大蝦指正。

上面定義一個預存程序updateattention,它有一個自訂類型 citext,用於將字串中類型換成不區分大小寫類型,它的定義如下:

 

CREATE OR REPLACE FUNCTION citext(character)
  RETURNS citext AS
'rtrim1'
  LANGUAGE internal IMMUTABLE STRICT
  COST 1;
ALTER FUNCTION citext(character) OWNER TO postgres;

 

下面是調用updateattention預存程序的代碼:

 

//擷取PostgreSQL的Data Access Objects
PWMIS.DataProvider.Data.AdoHelper db = MyDB.GetDBHelperByConnectionName("PostgreSQL");
//擷取PostgreSQL的參數對象
IDataParameter para = db.GetParameter(); 
para.ParameterName = "@dm";
para.DbType = DbType.AnsiString;
para.Value = "KF0355";
db.ExecuteNonQuery("updateattention",
                System.Data.CommandType.StoredProcedure,
                new System.Data.IDataParameter[] { para });

程式使用PDF.NET(PWMIS資料開發架構)的Data Access ObjectsAdoHelper來進行相關的資料訪問操作,它採用反射原廠模式,根據系統的配置執行個體化具體的資料訪問類,這裡使用的是PostgreSQL資料訪問類。

 

運行該程式,出現下面的錯誤:

PDF.NET AdoHelper 查詢錯誤:
DataBase ErrorMessage:ERROR: 42883:  function updatefundattention(text)  does not exist
SQL:updatefundattention
CommandType:StoredProcedure
Parameters:
Parameter["@jjdm"]    =    "KF0355"              //DbType=String

PDF.NET架構內建了日誌對象和異常對象,它能夠為你拋出詳細的錯誤資訊。

 

如果採用下面的方式調用,又沒有問題:

db.ExecuteNonQuery("select * from updateattention(@dm)",
                System.Data.CommandType.Text,
                new System.Data.IDataParameter[] { para });

------------------------------------------------------------------------------------

儘管該方式可以作為一種替代方案,但要用select * from 這種方式調用預存程序,總覺得很彆扭,還得找到問題的真正原因。

 

這個 "function ... does not exist" 的問題很難搜尋,最終在國外找到一篇文章討論類似的問題:

http://pgfoundry.org/forum/forum.php?thread_id=637&forum_id=519

文中有人說,可能是參數的類型轉換問題,但我這裡只是將參數進行了大小寫轉換,應該不會有類似Int32到Int64這類問題。

 

無賴,只有將調用預存程序的.NET程式碼一個一個排查,當注釋掉

para.DbType = DbType.AnsiString;

的時候,程式居然能夠正常運行通過了!

之前也曾經懷疑過是不是DbType的問題,但是當把滑鼠放到VS2010的編輯器中para 對象下面的時候,智能提示顯示 DbType="{String}".

預設情況下,參數對象的DbType屬性值是

DbType.String

難道

DbType.AnsiString==DbType.String ??

看了一下定義,它們是有區別的,DbType.AnsiString表示非Unicode的變長字串,DbType.String 表示Unicode的變長字串。

一般情況下,ANSI編碼錶示當前系統編碼,所以我猜想AnsiString在我的機器上是Gb2312編碼的,查了一下資料庫的編碼,它是UTF-8格式的,難怪難怪,PostgreSQL給我提示找不到 updatefundattention(text) 函數,注意下,實際上這個函數的參數不是text類型的,它實際上應該是 character 類型,PostgreSQL可以定義同名的函數,但函數可以有不同的參數類型,有點像C#的方法重載。

到此,問題似乎解決了,但還沒完:

 

VS2010的智能提示有Bug?

第一次有這個念頭我都覺得不可思議,因為以前在VS2008的時候曾經調試過類似的代碼,趕緊將上面的.net代碼中的參數對象換成其它資料庫類型的參數對象試試看:

//擷取PostgreSQL的Data Access Objects
PWMIS.DataProvider.Data.AdoHelper db = MyDB.GetDBHelperByConnectionName("PostgreSQL");
//使用 SqlServer 的參數對象
IDataParameter para = new SqlParameter(); 
para.ParameterName = "@dm";
para.DbType = DbType.AnsiString;
para.Value = "KF0355";
db.ExecuteNonQuery("updateattention",
                System.Data.CommandType.StoredProcedure,
                new System.Data.IDataParameter[] { para });

再此將游標放到para.DbType 上,這次提示正確了,是“{AnsiString}”;

將上面的代碼放到VS2008中再次驗證,智能提示正確,看來不是VS2010的Bug,呵呵。

 

故此,得到的結論:

PostgreSQL的.NET資料訪問驅動程式的參數對象DbType屬性存在一個設定成AnsiString之後查看該屬性的結果卻是String的Bug!

PS:雖然查看屬性的確有這樣一個Bug,但好像程式內部做了正確的處理,要不我的程式最終是無法運行通過的。

 

後記

PostgreSQL的.NET資料驅動程式的這個問題引起的問題使得我困擾了2天左右的時間,不得不發帖說明一下這個過程,現在國內有關PostgreSQL的資料太少,寫點東西供大家參考一下。

 

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.