设为首页 收藏本站
查看: 1277|回复: 0

[经验分享] PostgreSQL的.NET驱动程序Npgsql中参数对象的一个Bug

[复制链接]

尚未签到

发表于 2016-11-21 10:58:11 | 显示全部楼层 |阅读模式
  最近将公司的项目从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的数据访问对象
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数据开发框架)的数据访问对象AdoHelper来进行相关的数据访问操作,它采用反射工厂模式,根据系统的配置实例化具体的数据访问类,这里使用的是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的数据访问对象
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的资料太少,写点东西供大家参考一下。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-303396-1-1.html 上篇帖子: [原创]libpq-PostgreSQL客户端编程接口(一)----libpq中的数据库连接函数 下篇帖子: postgresql架构图(重要,不断更新,协作)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表