2010-02-05 85 views
1

我有一个接受经度和纬度参数的十进制(9,6)值的Firebird存储过程。它用于为用户创建联系人配置文件。在Firebird存储过程中使用十进制参数

当我尝试创建和使用这些小数参数,我得到一个转换错误:

Value was too large or too small for an Int32.

下面是如何创建的ADO.Net连接:

FbConnection dbConn = new FbConnection(ConnectionString); 

进一步对,这里的在那里我设置了命令:

 IDbCommand command = _Connection.CreateCommand(); 
     command.Connection = _Connection; 
     command.CommandText = "CREATECONTACT"; 
     command.CommandType = CommandType.StoredProcedure; 

我用来创建ADO.Net参数的代码看就像这样:

IDataParameter param21 = command.CreateParameter(); 
param21.ParameterName = "GEOLAT"; 
param21.DbType = DbType.Decimal; 
param21.Value = 3.14m; 

后所有的参数都被添加我叫command.ExecuteScalar()得到的只是创造了一个(希望)的使用ContactID的价值。

int contactId = Convert.ToInt32(command.ExecuteScalar(), CultureInfo.InvariantCulture); 

这不是导致问题的Convert.ToInt32。从ExecuteScalar()中抛出异常。我得到同样的错误,如果命令是这样的:

object result = command.ExecuteScalar(); 

程序工作正常,如果为GeoLat和GeoLong值是整数值(如72或0),但如果我试图通过一个十进制值, 它失败。例如:

IDataParameter param21 = command.CreateParameter(); 
param21.ParameterName = "GEOLAT"; 
param21.DbType = DbType.Int32; 
param21.Value = 12; 

我在这里做错了什么?

我对Firebird 2.1.3数据库使用Firebird .NET数据提供程序2.5.1。

UPDATE:在@ bluecoder的请求中,我试图从源代码构建.NET数据提供程序。但是我在GdsStatement.cs的第731行得到一个编译错误。

int processedItems = (rowDescs[part] != null ? rowDescs[part].Count : 0); 

的错误是:

There exist both implicit conversions from "short" to "int" and from "int" to "short".

更改线路731本:

int processedItems = (rowDescs[part] != null ? (int) rowDescs[part].Count : 0); 

允许代码编译我的机器上。

使这个代码更改后,我能够运行我的测试,并成功地在我的存储过程中使用小数。

看来,错误的触发器是我返回受更新语句影响的行数作为过程的一部分。

UPDATE2:下面是SQL存储过程的完整源代码。它用于在我的数据库中创建一个hCard记录。

SET TERM^; 
RECREATE PROCEDURE CREATECONTACT (
TEMPLATECODE  SMALLINT, 
CREATEUSERID  INTEGER, 
CREATEDATE  TIMESTAMP, 
SECURITYCODE  SMALLINT, 
LINKTEXT   VARCHAR(255), 
GUID    VARCHAR(200), 
GIVENNAME  VARCHAR(200), 
FAMILYNAME  VARCHAR(200), 
ADDITIONALNAME VARCHAR(200), 
HONORIFICPREFIX VARCHAR(200), 
HONORIFICSUFFIX VARCHAR(200), 
NICKNAME   VARCHAR(200), 
PHOTOLOCALFILEID INTEGER, 
LOGOLOCALFILEID INTEGER, 
BIRTHDAY   TIMESTAMP, 
JOBTITLE   VARCHAR(200), 
"ROLE"   VARCHAR(200), 
ORGANIZATION  VARCHAR(255), 
NOTE    BLOB SUB_TYPE TEXT, 
GEOLAT   DECIMAL(9,6), 
GEOLONG   DECIMAL(9,6)) 
RETURNS (
ENTITYID   INTEGER) 
AS 
BEGIN 
EXECUTE PROCEDURE CreateEntity :TEMPLATECODE, :CREATEUSERID, :CREATEDATE, :SECURITYCODE, :LinkText 
    RETURNING_VALUES EntityId; 

INSERT INTO CONTACT (EntityId, GUID, GIVENNAME, FAMILYNAME, ADDITIONALNAME, 
HONORIFICPREFIX, HONORIFICSUFFIX, NICKNAME, PHOTOLOCALFILEID, LOGOLOCALFILEID, 
BIRTHDAY, JOBTITLE, "ROLE", ORGANIZATION, NOTE, GEOLAT, GEOLONG) 
VALUES (:EntityId, :GUID, :GIVENNAME, :FAMILYNAME, :ADDITIONALNAME, 
:HONORIFICPREFIX, :HONORIFICSUFFIX, :NICKNAME, :PHOTOLOCALFILEID, 
:LOGOLOCALFILEID, :BIRTHDAY, :JOBTITLE, :ROLE, :ORGANIZATION, :NOTE, 
:GEOLAT, :GEOLONG); 
SUSPEND; 
END^ 
SET TERM ;^

UPDATE3:我刚与新客户火鸟2.5.2版本尝试这样做,它仍然有问题。我认为这是一个错误。我要在Firebird Tracker上报告。

UPDATE4:糟糕。我发现我在GAC中对Firebird Client 2.5.1有一个陈旧的参考。 Firebird Client 2.5.2确实解决了这个问题。

+0

您的程序是否在IBExpert这样的IDE中工作? – 2010-02-05 16:47:33

+0

我还没有在IDE中尝试过它,但是如果我为GEOLAT和GEOLONG传递整数值,存储过程将正常工作。如果它们被输入为小数,它将失败。 – dthrasher 2010-02-05 21:03:59

+0

我刚刚在Firebird Maestro IDE中尝试了我的过程,并且它可以正常使用十进制值。 – dthrasher 2010-02-05 21:18:27

回答

0

我刚刚发现我在GAC中有一个对Firebird Client 2.5.1的陈旧引用。删除这个引用后,我能够成功运行我的测试用例。

火鸟版本2.5.2的.NET提供程序没有我在我的问题中描述的问题。解决方案是升级到最新版本的Firebird .NET Provider。

+0

我很高兴你终于搞定了:) – bluecoder 2010-02-23 17:14:33

2

检查显而易见的第一:

1)您在Parameter.DbType的确定没有被设置为DbType.Int32?

2)你能发布你的调试器遇到错误的实际代码吗? (我假设上面是伪代码)

3)您是否验证了失败是否在Parameter.Value赋值行? (而不是在命令执行,例如)


来源
下载.NET提供源 - Provider
7zip的提取源(如果你没有的话) - 7Zip

构建
[备份您当前的源正在修改任何东西]
1)右键单击您的C#解决方案并选择添加 - >现有的解决方案
2)选中*从您提取提供商源
目录的.csproj [.. \ NETProvider \源\ FirebirdSql \数据\ FirebirdSql.Data.FirebirdClient.csproj]
3)右点击FirebirdClient项目并构建它
4)将应用程序中的FirebirdSql.Data.FirebirdClient引用更改为您刚刚编译的版本
[.. \ Data \ bin \ Debug \ FirebirdSql.Data.FirebirdClient.dll]

现在您应该能够进入(F11)您的ExecuteScalar语句并查看转换异常正在引发的位置。

让我知道是否有任何意义。我很有兴趣看到你找到的东西

+0

我确定在所有情况下参数都设置为DbType.Decimal。命令执行期间发生异常,而不是参数分配。我会将它发生的行粘贴到我的问题中。 – dthrasher 2010-02-05 20:48:31

+0

1)ExecuteScalar是否返回一个对于Int32来说太大的数字来处理? (> 2,147,483,647) 2)您正在执行的sql语句/过程/表是否具有正确的数据类型? (在数据库中,数据类型是不兼容的) – bluecoder 2010-02-05 21:10:48

+0

1)不,我的联系人表的ID在数百个。我没有接近Int32的返回值限制。 2)存储过程和表都有正确的类型。该程序在Firebird Maestro IDE中执行得很好。 – dthrasher 2010-02-05 21:20:45