Ошибка преобразования int в nvarchar

Эта ошибка меня очень смутила. У меня есть хранимая процедура с двумя выходными параметрами, как определено ниже

@agentNumber int OUTPUT,
@currentAgentNum int OUTPUT,

Затем они заполняются с помощью операторов SELECT ниже.

SELECT @agentNumber = AgentNumber
FROM AgentIdentification
WHERE AgentTaxId = @ssn

SELECT @currentAgentNum = AgentNumber
FROM UniqueAgentIdToAgentId
WHERE AgentId = @agentId

В базе данных AgentNumber определен в обеих таблицах как int. Однако, когда я вызываю эту хранимую процедуру в своем коде C #, я получаю исключение SQL, в котором говорится:

Ошибка преобразования типа данных int в nvarchar.

Если я изменю типы данных выходных параметров на nvarchar, код будет выполнен, однако он вернет только первую цифру целого числа. Ниже показано, как переменные определены в коде C #.

SqlParameter outNewAgentNumber = new SqlParameter("@agentNumber", "");//Output parameter - leave blank
SqlParameter outCurrentAgentNumber = new SqlParameter("@currentAgentNum", "");//Output parameter - leave blank

outNewAgentNumber.Direction = ParameterDirection.Output;
outCurrentAgentNumber.Direction = ParameterDirection.Output;

Я добавляю эти параметры к объекту SqlCommand, указываю соответствующую базу данных и commandType, затем использую .ExecuteNonQuery() для вызова процедуры. Опять же, что меня действительно смутило, так это сообщение об ошибке, в котором говорится, что я использую nvarchar в качестве типа данных, который может (насколько мне известно) относиться только к чему-то на стороне базы данных. Однако, как я уже сказал, я дважды / трижды проверил, и оба AgentNumber столбца относятся к типу int.

РЕДАКТИРОВАТЬ

Изменение деклараций sqlParameter на начальное значение 0 решило эту проблему. Теперь я столкнулся с той же проблемой с двумя другими параметрами.

SqlParameter outOperator = new SqlParameter("@operator", "");//Output parameter - leave blank
SqlParameter outDate = new SqlParameter("@date", "");//Output parameter - leave blank

person NealR    schedule 20.08.2012    source источник


Ответы (2)


Эти две строки являются виновниками:

SqlParameter outNewAgentNumber = new SqlParameter("@agentNumber", "");
SqlParameter outCurrentAgentNumber = new SqlParameter("@currentAgentNum", "");

Если указать в качестве второго параметра пустую строку (""), среда выполнения ADO.NET предполагает, что это параметр строки. И поскольку вы не указали длину, вероятно, по умолчанию используется только один символ (поэтому он возвращает только первую цифру).

Итак, я бы рекомендовал всегда явно определять тип данных (а если это строка - также определять длину!) Для ваших параметров SQL:

SqlParameter outNewAgentNumber = new SqlParameter("@agentNumber", SqlDbType.Int);
outNewAgentNumber.Direction = ParameterDirection.Output;
outNewAgentNumber.Value = 0;

or

SqlParameter outNewAgentNumber = new SqlParameter("@agentNumber", SqlDbType.NVarChar, 50);
outNewAgentNumber.Direction = ParameterDirection.Output;
outNewAgentNumber.Value = "";
person marc_s    schedule 20.08.2012
comment
Почему вы рекомендуете явно определять длину параметра? Стоимость того, чтобы позволить .net и SQL-серверу получить его для вас, чрезвычайно мала, и если вы ошибетесь (или он изменится), данные будут автоматически усечены. Это действительно лучший подход? - person Conrad Frix; 20.08.2012
comment
@ConradFrix: проблема может быть в том, что если вы не укажете длину, она может быть установлена ​​на 1 - обычно не то, что вы хотите .... - person marc_s; 20.08.2012
comment
@marc_s Вы предлагаете, чтобы размер параметра был получен из значения параметра. Потому что это не то, что происходит. И почему вы устанавливаете значение, когда направление не в (ParameterDirection.InputOutput, ParameterDirection.Input) - person Conrad Frix; 20.08.2012
comment
@ConradFrix: ну, если направление НЕ по умолчанию (.Input), вы должны его установить - нет ?? - person marc_s; 20.08.2012
comment
@marc_s извините, я должен был написать это по-другому. Я хотел спросить, почему вы установили Parameter.Value, когда направление параметра выводится? - person Conrad Frix; 21.08.2012
comment
@ConradFrix: Мне кажется, я припоминаю случаи, когда я сталкивался с исключениями, если значения - даже выходных параметров - не были инициализированы. Так что стало привычкой просто всегда инициализировать эти значения чем-то, чтобы я также мог видеть, было ли значение возвращено из процесса - или у меня все еще есть начальные значения. - person marc_s; 21.08.2012

Изменять

SqlParameter outNewAgentNumber = new SqlParameter("@agentNumber", "");//Output parameter - leave blank 
SqlParameter outCurrentAgentNumber = new SqlParameter("@currentAgentNum", "");//Output parameter - leave blank 

to

SqlParameter outNewAgentNumber = new SqlParameter("@agentNumber", 0);//Output parameter - leave blank 
SqlParameter outCurrentAgentNumber = new SqlParameter("@currentAgentNum", 0);//Output parameter - leave blank 

В вашем коде вы изначально указываете значение как строку, потому что вы передаете ему строку, который сопоставляется с varchar при переходе от типа CLR к типу данных SQL.

Как только среда выполнения видит его как строку, она сохраняет один и тот же тип во всем коде, поэтому, если вы присваиваете числовое (int) значение, она все равно видит его как строку. Уловка состоит в том, чтобы в первую очередь назначить ему правильный тип данных.

person David    schedule 20.08.2012