У меня есть хранимая процедура Firebird, которая принимает десятичные (9,6) значения для параметров широты и долготы. Используется для создания профиля контакта для пользователя.
Когда я пытаюсь создать и использовать эти десятичные параметры, я получаю ошибку преобразования:
Значение было слишком большим или слишком маленьким для 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 .NET 2.5.1 против базы данных Firebird 2.1.3.
ОБНОВЛЕНИЕ: По запросу @ bluecoder я попытался построить поставщик данных .NET из исходного кода. Но я получаю ошибку компиляции в строке 731 файла GdsStatement.cs.
int processedItems = (rowDescs[part] != null ? rowDescs[part].Count : 0);
Ошибка:
Существуют неявные преобразования из «short» в «int» и из «int» в «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 : Я только что попробовал это с новым выпуском Firebird Client 2.5.2, и проблема все еще остается. Я думаю, что это ошибка. Я собираюсь сообщить об этом на Firebird Tracker .
UPDATE4 : Упс. Я обнаружил, что в GAC у меня была устаревшая ссылка на Firebird Client 2.5.1. Firebird Client 2.5.2 решает проблему.