PostgreSQL是一个使用广泛的免费开源的数据库,与MySQL比较,它更适合复杂的企业计算任务,而MySQL在互联网领域应用更为广泛,究其原因,可能是PostgreSQL拥有支持最多的数据类型,甚至包括数组类型,IP地址类型等,可以使用C,SQL,PL/Pgsql,Phython等多种方式编写强大的自定义函数,因此特别适合处理复杂的计算问题。如果想要将SqlServer数据库迁移到其它类型的数据库,PostgreSQL是比较好的选择。

尽管PostgreSQL使用比较广泛,但在国内相关资料太少,我们在数据库迁移的过程中,遇到了不少问题,比如我的上一篇文章PostgreSQL的.NET驱动程序Npgsql中参数对象的一个Bug 中关于“找不到函数名”的问题,解决起来比较“辣手”,可以使用“追踪”来形容了。本篇继续对这个问题进行深入探究。

1,问题回顾:
 在上一篇文章中说到,有一个PostgreSQL函数 updateattention ,它有一个自定义的函数参数,下面是函数头:

CREATE OR REPLACE FUNCTION updateattention(dm citext)
  RETURNS void AS
$BODY$
--函数体略

参数dm 的类型是citex,一个自定义的数据类型,使用它来作为函数参数或者变量的类型,在进行数据查询的时候可以不区分大小写,它的定义是:

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

下面是调用使用C#调用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框架内置了日志对象和异常对象,它能够为你抛出详细的错误信息,参看“PDF.NET的SQL日志 ”

2,问题聚焦

一开始还以为是函数名大小写的问题,仔细核对后发现没有问题,然后尝试对代码进行仔细排查。

将上面的程序中第6行代码

para.DbType = DbType.AnsiString;


注释掉,程序运行通过,怀疑参数类型不能够设置成AnsiString,设置成下面的方式:

para.DbType = DbType.String;


程序依然运行不通过,抛出上面同样的错误,只有将这行代码注释掉才可以允许通过,思索很久仍然没有结果,于是昨天写了本文开头说的那篇文章(PostgreSQL的.NET驱动程序Npgsql中参数对象的一个Bug)。

今天再次将目光聚集在错误信息的函数参数上:

updatefundattention(text)

难道PostgreSQL的数据类型text 对应的.NET程序类型既不是String,也不是AnsiString?

又搜索了下,在http://npgsql.projects.postgresql.org/docs/manual/UserManual.html 找到了一张数据类型对照表:

Supported data types

Npgsql supports the following data types:

Postgresql Type NpgsqlDbType System.DbType Enum .Net System Type
int8 Bigint Int64 Int64
bool Boolean Boolean Boolean
Box, Circle, Line, LSeg, Path, Point, Polygon Box, Circle, Line, LSeg, Path, Point, Polygon Object Object
bytea Bytea Binary Byte[]
date Date Date DateTime, NpgsqlDate
float8 Double Double Double
int4 Integer Int32 Int32
money Money Decimal Decimal
numeric Numeric Decimal Decimal
float4 Real Single Single
int2 Smallint Int16 Int16
text Text String String
time Time Time DateTime, NpgsqlTime
timetz Time Time DateTime, NpgsqlTimeTZ
timestamp Timestamp DateTime DateTime, NpgsqlTimestamp
timestamptz TimestampTZ DateTime DateTime, NpgsqlTimestampTZ
interval Interval Object TimeSpan, NpgsqlInterval
varchar Varchar String String
inet Inet Object NpgsqlInet, IPAddress
(there is an implicity cast operator to convert NpgsqlInet objects into IPAddress if you need to use IPAddress and have only NpgsqlInet)
bit Bit Boolean Boolean, Int32
(If you use an Int32 value, odd values will be translated to bit 1 and even values to bit 0)
uuid Uuid Guid Guid
array Array Object Array
In order to explicitly use array type, specify NpgsqlDbType as an 'OR'ed type: NpgsqlDbType.Array | NpgsqlDbType.Integer for an array of Int32 for example.

可以看到 数据库的text 类型是可以对应.net程序的String类型的,看来问题的关键的确是函数参数类型问题

为了验证这个想法,将函数的参数类型改为Varchar类型:

CREATE OR REPLACE FUNCTION updateattention(dm varchar)
  RETURNS void AS
$BODY$
--函数体略

再次运行前面说的.net数据访问程序,运行通过!

故此得到结论:

PostgreSQL数据库的函数中使用“自定义数据类型”,在.NET程序可能无法设置正确的DbType,从而出现找不到函数名的错误!

3,“灵异现象”分析

前面说,将

para.DbType = DbType.AnsiString;
代码注释即可,也就是不对NpgsqlParameter.DbType 设置任何值,那么DbType的缺省值是什么呢?

在VS2010的“即时窗口”打印了一下未设置值的para.DbType,发现它的值是:

String

由于上一篇文章已经验证Npgsql的参数对象DbType无论怎么设置,获取该属性值的时候都是String,所以还是无法得知它的默认属性值是什么。

于是一个很偶然的念头出现:

NpgsqlParameter对象的默认值是不是Object类型?

另外我们的函数使用了自定义的citext类型,所以很可能需要使用DbType.Object类型。

重新修改代码成下面的方式:

//获取PostgreSQL的数据访问对象
PWMIS.DataProvider.Data.AdoHelper db = MyDB.GetDBHelperByConnectionName("PostgreSQL");
//获取PostgreSQL的参数对象
IDataParameter para = db.GetParameter(); 
para.ParameterName = "@dm";
para.DbType = DbType.Object;
para.Value = "KF0355";
db.ExecuteNonQuery("updateattention",
                System.Data.CommandType.StoredProcedure,
                new System.Data.IDataParameter[] { para });

运行程序,正常通过,看来问题找到了,就是它,在PostgreSQL的自定义类型函数参数中,.net程序的存储过程调用参数应该设置成 DbType.Object!

转载于:https://www.cnblogs.com/bluedoctor/archive/2011/05/19/2051271.html

.net访问PostgreSQL数据库发生“找不到函数名”的问题追踪相关推荐

  1. Serverless 解惑——函数计算如何访问 PostgreSQL 数据库

    函数计算(Function Compute):函数计算 是事件驱动的全托管计算服务.使用函数计算,您无需采购与管理服务器等基础设施,只需编写并上传代码.函数计算为您准备好计算资源,弹性地可靠地运行任务 ...

  2. C#访问postgresql数据库类MyPostDB的实现

    为了访问PostgreSQL数据库,需要从pgfoundry网站,下载Npgsql .Net Data Provider for Postgresql的组件. 访问 URL:http://pgfoun ...

  3. python postgresql跨数据库查询_python访问PostgreSQL数据库之连接库Psycopg2

    python访问PostgreSQL数据库之连接库Psycopg2 作者:佣工7001 由于要在python访问PostgreSQL数据库,需要一个符合DB-API的连接库.通过搜索,锁定两个候选库: ...

  4. 函数计算如何访问 PostgreSQL 数据库

    函数计算(Function Compute):函数计算 是事件驱动的全托管计算服务.使用函数计算,您无需采购与管理服务器等基础设施,只需编写并上传代码.函数计算为您准备好计算资源,弹性地可靠地运行任务 ...

  5. windows下c 用mysql数据库_Windows环境下C/C++访问PostgreSQL数据库

    PostgreSQL是一款在Linux环境下应用十分广泛的轻量级关系型数据库,大家都听说过MySQL,却对PostgreSQL鲜有耳闻,它其实在性能.应用领域上和MySQL不相上下.网上关于Windo ...

  6. 配置RODBC访问PostgreSQL数据库

    走了不少弯路,总算把这个问题搞定,贴到这里分享给大家. 1:下载安装PostgreSQL的ODBC驱动 http://www.postgresql.org/ftp/odbc/versions/msi/ ...

  7. 使用Go语言ORM库worm访问PostgreSQL数据库

    worm是一款方便易用的Go语言ORM库,worm具有使用简单,运行性能高,功能强大的特点.本文介绍如何使用worm来访问postgres数据库. 创建实体类 CREATE TABLE users(i ...

  8. PostgreSQL数据库统计信息——analyze执行函数

    在执行do_analyze_rel函数之前需要确定采样函数,如下: 如果是普通表或者物化视图,则采样函数采用acquire_sample_rows:relpages由RelationGetNumber ...

  9. bash shell脚本访问PostgreSQL的三种方式

    bash脚本里有三种方式访问PostgreSQL数据库 但前提是要设置密码文件.当然对于有系统对应账户的数据库角色可以绕过密码登录环节,如 1 $ sudo -u postgres psql 或 1 ...

最新文章

  1. mysql contains函数_多属性、多分类MySQL模式设计
  2. InstallShield For .Net制作.Net项目安装包之完整代码
  3. JAVA多线程--线程阻塞与唤醒
  4. iterator [ɪtə'reɪtə] 遍历器
  5. Could not parse mapping document from input stream hibernate配置异常
  6. XMLHttpReq.onreadystatechange 传递参数
  7. VC2008下安装OpenCV2.3.1
  8. 【Json工具类】json数据格式转换
  9. 大数据:新动力 新机遇 新途径
  10. 线阵相机参数选择 照明方式
  11. java word checkbox_springmvc poi 导出word 复选框 怎么用
  12. 超声波清洗机是什么?
  13. 本科计算机专业考研集成电路,集成电路工程专业考研院校排名
  14. 如何判断两条线段是否相交
  15. phpstorm注册码 激活 授权码 License server
  16. IOS 点击空白处隐藏键盘的几种方法
  17. 人工智能之人工神经网络
  18. 如何使用repo管理本地私有仓库
  19. ERROR Error: command failed: pnpm install --reporter silent --shamefully-hoist 错误解决办法
  20. 35岁的程序员被优化,是市场经济的必然选择吗

热门文章

  1. Redis配置文件常用配置详解
  2. Vue调用后端接口http ajax请求组件封装及proxyTable跨域问题解决超详细案例
  3. Java方法案例--比较两个值是否相等
  4. 权限控制的两种主要方式详述
  5. 【已解决】R语言,在线升级
  6. 数据库70多张表设计的一些思考…
  7. python(matplotlib2)——legend图例,Annotation图片注解
  8. eclipse总是运行上一个程序结果
  9. java微妙_10个微妙的Java编码最佳实践
  10. windows server 2012 FTP 服务器 / 创建服务器