PostgreSQL的.NET驱动程序Npgsql中参数对象的一个Bug

数据库 其他数据库 PostgreSQL
最近将公司的项目从SqlServer移植到PostgreSQL数据库上来,在调用数据库的存储过程(自定义函数)的时候,发现一个奇怪的问题,老是报函数无法找到。

最近将公司的项目从SqlServer移植到PostgreSQL数据库上来,在调用数据库的存储过程(自定义函数)的时候,发现一个奇怪的问题,老是报函数无法找到。

先看一个PgSQL存储过程:

  1. CREATE OR REPLACE FUNCTION updateattention(dm citext)  
  2. RETURNS void AS 
  3. $BODY$  
  4. DECLARE 
  5. BEGIN 
  6. update ZB set gzd=COALESCE(gzd,0)+1 where ZB.dm=$1 ;  
  7. END;  
  8. $BODY$  
  9. LANGUAGE plpgsql VOLATILE  
  10. COST 100;  
  11. ALTER FUNCTION updateattention(citext) OWNER TO postgres; 

在PostgreSQL中,函数和存储过程没有区别,这里我们把没有返回值的函数叫做存储过程吧,也许表诉的不太准确,还望大虾指正。

上面定义一个存储过程updateattention,它有一个自定义类型 citext,用于将字符串中类型换成不区分大小写的类型,它的定义如下:

  1. CREATE OR REPLACE FUNCTION citext(character)  
  2. RETURNS citext AS 
  3. 'rtrim1' 
  4. LANGUAGE internal IMMUTABLE STRICT  
  5. COST 1;  
  6. ALTER FUNCTION citext(character) OWNER TO postgres; 

下面是调用updateattention存储过程的代码:

  1. //获取PostgreSQL的数据访问对象  
  2. PWMIS.DataProvider.Data.AdoHelper db = MyDB.GetDBHelperByConnectionName("PostgreSQL");  
  3. //获取PostgreSQL的参数对象  
  4. IDataParameter para = db.GetParameter();  
  5. para.ParameterName = "@dm";  
  6. para.DbType = DbType.AnsiString;  
  7. para.Value = "KF0355";  
  8. db.ExecuteNonQuery("updateattention",  
  9. System.Data.CommandType.StoredProcedure,  
  10. new System.Data.IDataParameter[] { para }); 

程序使用PDF.NET(PWMIS数据开发框架)的数据访问对象AdoHelper来进行相关的数据访问操作,它采用反射工厂模式,根据系统的配置实例化具体的数据访问类,这里使用的是PostgreSQL数据访问类。

运行该程序,出现下面的错误:

PDF.NET AdoHelper 查询错误:

  1. DataBase ErrorMessage:ERROR: 42883: function updatefundattention(text) does not exist  
  2. SQL:updatefundattention  
  3. CommandType:StoredProcedure  
  4. Parameters:  
  5. Parameter["@jjdm"] = "KF0355" //DbType=String 

PDF.NET框架内置了日志对象和异常对象,它能够为你抛出详细的错误信息。

如果采用下面的方式调用,又没有问题:

  1. db.ExecuteNonQuery("select * from updateattention(@dm)",  
  2. System.Data.CommandType.Text,  
  3. 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代码中的参数对象换成其它数据库类型的参数对象试试看:

  1. //获取PostgreSQL的数据访问对象  
  2. PWMIS.DataProvider.Data.AdoHelper db = MyDB.GetDBHelperByConnectionName("PostgreSQL");  
  3. //使用 SqlServer 的参数对象  
  4. IDataParameter para = new SqlParameter();  
  5. para.ParameterName = "@dm";  
  6. para.DbType = DbType.AnsiString;  
  7. para.Value = "KF0355";  
  8. db.ExecuteNonQuery("updateattention",  
  9. System.Data.CommandType.StoredProcedure,  
  10. new System.Data.IDataParameter[] { para }); 

再此将光标放到para.DbType 上,这次提示正确了,是“{AnsiString}”;

将上面的代码放到VS2008中再次验证,智能提示正确,看来不是VS2010的Bug,呵呵。

故此,得到的结论:

PostgreSQL的.NET数据访问驱动程序的参数对象DbType属性存在一个设置成AnsiString之后查看该属性的结果却是String的Bug!

PS:虽然查看属性的确有这样一个Bug,但好像程序内部做了正确的处理,要不我的程序最终是无法运行通过的。

后记

PostgreSQL的.NET数据驱动程序的这个问题引起的问题使得我困扰了2天左右的时间,不得不发帖说明一下这个过程,现在国内有关PostgreSQL的资料太少,写点东西供大家参考一下。

原文链接:http://www.cnblogs.com/bluedoctor/archive/2011/05/18/2050276.html

【编者推荐】

  1. 思科推新数据中心解决方案支持SQL Server
  2. 数据库日常维护常用的脚本部分收录
  3. SQL Server表最小行的一个纠结问题
  4. 云端数据库:微软SQL Azure及其应用场景
  5. SQL点滴之收集SQL Server线程等待信息

 

 

责任编辑:艾婧 来源: 博客园
相关推荐

2011-05-31 10:38:14

PostgreSQL

2011-05-20 08:54:35

PostgreSQL

2017-10-24 17:03:48

Linux驱动程序编译

2009-09-14 17:08:02

WebFormView

2010-05-10 15:53:24

Unix系统

2015-08-24 10:07:13

程序员bug

2018-08-29 13:33:02

Windows 10修复驱动程序

2009-06-15 14:18:00

netbeans配置JDBC驱动程序

2011-01-06 16:29:08

linuxtasklet机制

2009-07-06 18:17:46

JDBC驱动程序

2013-10-31 16:29:10

Linux内核

2022-03-08 09:25:52

数据库系统MongoDB

2021-05-06 13:45:54

漏洞网络安全网络攻击

2022-05-19 08:33:53

漏洞恶意软件

2021-11-29 07:55:45

Linux GPIO Linux 系统

2019-03-27 13:20:31

Windows 10更新驱动程序

2009-11-04 13:14:59

Windows Emb驱动程序

2009-07-20 18:01:38

Oracle JDBC

2018-11-19 10:15:26

Windows 10WiFi驱动程序

2011-09-08 18:34:33

WindowsXP驱动程序
点赞
收藏

51CTO技术栈公众号