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

   
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!

 

 

网站地图xml地图