Получение ошибки преобразования типа данных nvarchar в int из приложения (C #), но не при запуске SP самостоятельно - PullRequest
5 голосов
/ 19 августа 2011

Моя компания заключила контракт с разработчиком на создание новой программы инвентаризации, которая заменит старую устаревшую.К сожалению для меня разработчик ушел до отладки приложения, и в результате я застрял, пытаясь выяснить 2 проблемы с моим ограниченным знанием C #, поэтому достаточно моей истории о рыданиях, вот моя проблема.

Большинство приложений работает нормально, но при попытке получить инвентаризацию от наших специалистов я получаю сообщение об ошибке (SqlException не обрабатывается пользовательским кодом - Ошибка преобразования данных tyoe nvarchar в int).Я смотрел на код, таблицы и хранимые процедуры, но мне не повезло найти проблему. Надеюсь, кто-то может указать на то, что мне здесь не хватает.Ниже приведена трассировка стека, кодирование C #, хранимая процедура и таблицы.

[SqlException (0x80131904): Error converting data type nvarchar to int.]
System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)   +2062078
System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) +5050204
System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() +234
System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler,   SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)  +2275
System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) +215
System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) +987
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) +162
System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe) +178
System.Data.SqlClient.SqlCommand.ExecuteNonQuery() +137
DAL.DBManager.ExecuteNonQuery(CommandType commandType, String commandText) in C:\Users\kevin.price\Documents\Visual Studio 2010\Projects\Equip\DAL\DAL.cs:221
Equip.EquipmentMainPage.btnReceiveProcess_Click(Object sender, EventArgs e) in C:\Users\kevin.price\Documents\Visual Studio 2010\Projects\Equip\EquipmentMainPage.aspx.cs:358
System.Web.UI.WebControls.Button.OnClick(EventArgs e) +118
System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +112
System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +10
System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +13
System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +36
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +5563

Фрагмент кода C #

  protected void btnReceiveProcess_Click(object sender, EventArgs e)
    {
        string[] lines = txtReceive.Text.Split('\n');

        dm.Open();
        for (int I = 0; I < lines.GetLength(0); I++)
        {
            dm.CreateParameters(9);
            dm.AddParameters(0, "@OP", "RcvdTech");
            dm.AddParameters(1, "@BatchID", "{" + guid + "}");
            dm.AddParameters(2, "@BatchDate", DateTime.Now.Date);
            dm.AddParameters(3, "@boxnum", lines.GetValue(I));
            dm.AddParameters(4, "@boxtype", Convert.ToString(BoxType(lines.GetValue(I).ToString())));
            dm.AddParameters(5, "@status", "RcvdTech");
            dm.AddParameters(6, "@modby", user);
            dm.AddParameters(7, "@corp", null);
            dm.AddParameters(8, "@cominvoice", null);


            {

            }

            dm.ExecuteNonQuery(CommandType.StoredProcedure, "bxReceive");

            dm.Close();

            script =
               "<script type='text/javascript'>alert('Process Complete');</script>";
            var page = HttpContext.Current.CurrentHandler as Page;
            if ((!page.ClientScript.IsClientScriptBlockRegistered("alert")))
            {
                page.ClientScript.RegisterClientScriptBlock(GetType(), "alert", script);
            }
        }

Хранимая процедура

ALTER PROCEDURE [dbo].[bxReceive]
-- Add the parameters for the stored procedure here
@OP varchar(50), @BatchID varchar(50), @BatchDate varchar(50),
@boxnum varchar(50), @boxtype int, @status varchar(50), @modby varchar(50), @corp varchar(50), @cominvoice varchar(50) 
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;

-- Insert statements for procedure here
Declare @msg varchar(50)
set @boxnum = replace(@boxnum,char(13),'')
set @BatchID = left(@BatchID,CHARINDEX(char(125),@BatchID))
set @msg = 'White'

if ltrim(rtrim(@OP)) = 'RcvdTech'
    begin
        set @boxtype = isnull((select top 1 isnull(boxtype,9) from boxHistory where boxnum = rtrim(@boxnum) and boxtype <> 0),9)
    end 


--Begin Try
--begin transaction

IF LEN(@boxnum) > 0 and (SELECT count(*)FROM dbo.bxReceived where BatchID = rtrim(@BatchID)and [boxnum] = rtrim(@boxnum) and [corp] = rtrim(@corp) and [cominvoice] = rtrim(@cominvoice) ) = 0
Begin
INSERT INTO dbo.bxReceived
           ([BatchID]
           ,[BatchDate]
           ,[boxnum]
           ,[boxtype]
           ,[status]
           ,[modby]
           ,[corp]
           ,[cominvoice])

select rtrim(@BatchID), rtrim(@BatchDate),rtrim(@boxnum), @boxtype, rtrim(@status), rtrim(@modby), rtrim(@corp), rtrim(@cominvoice)

if ltrim(rtrim(@OP)) = 'newstock'
    begin
        if (select COUNT(*) from boxHistory where boxnum = rtrim(@boxnum) and enddate is null) = 0
            begin 
                INSERT INTO [boxHistory]
                ([boxnum],[boxtype],[tech],[status],[newstatus]
                ,[account],[startdate],[enddate],[modby],[ReqActn],[ActnReq],[corp],[cominvoice])

                select rtrim(@boxnum), @boxtype,0, rtrim(@status),null,null,GETDATE(), null, rtrim(@modby),null,null,@corp, @cominvoice
            end
        else
            begin
                update [boxHistory]
                    set [newstatus] = rtrim(@status), [enddate] = GETDATE()
                where boxnum = rtrim(@boxnum) and enddate is null 

                INSERT INTO [boxHistory]
                ([boxnum],[boxtype],[tech],[status],[newstatus]
                ,[account],[startdate],[enddate],[modby],[ReqActn],[ActnReq],[corp],[cominvoice])

                select rtrim(@boxnum), @boxtype,0, rtrim(@status),null,null,GETDATE(), null, rtrim(@modby),'Y','Was active in Inventory',@corp,@cominvoice
            end
    end


if ltrim(rtrim(@OP)) = 'RcvdTech'
    begin
        if (select COUNT(*) from boxHistory where boxnum = rtrim(@boxnum) and enddate is null) > 0
            begin
                update [boxHistory]
                    set [newstatus] = rtrim(@status), [enddate] = GETDATE()
                where boxnum = rtrim(@boxnum) and enddate is null 

                INSERT INTO [boxHistory]
                ([boxnum],[boxtype],[tech],[status],[newstatus]
                ,[account],[startdate],[enddate],[modby],[ReqActn],[ActnReq])

                select rtrim(@boxnum), @boxtype,0, rtrim(@status),null,null,GETDATE(), null, rtrim(@modby),null,null
            end
        else
            begin 
                INSERT INTO [boxHistory]
                ([boxnum],[boxtype],[tech],[status],[newstatus]
                ,[account],[startdate],[enddate],[modby],[ReqActn],[ActnReq])

                select rtrim(@boxnum), @boxtype,0, rtrim(@status),null,null,GETDATE(), GETDATE(), rtrim(@modby),'Y','Was not active in Inventory'
                set @msg = 'RED'
            end
    end

Таблицы

[dbo].[boxHistory](
[id] [bigint] IDENTITY(1,1) NOT NULL,
[boxnum] [varchar](50) NOT NULL,
[boxtype] [int] NULL,
[tech] [int] NULL,
[status] [varchar](50) NULL,
[newstatus] [varchar](50) NULL,
[account] [varchar](50) NULL,
[startdate] [datetime] NULL,
[enddate] [datetime] NULL,
[modby] [varchar](50) NULL,
[ReqActn] [char](1) NULL,
[ActnReq] [varchar](50) NULL,
[corp] [varchar](50) NULL,
[cominvoice] [varchar](50) NULL,


[dbo].[bxReceived](
[BatchID] [varchar](100) NULL,
[BatchDate] [varchar](50) NULL,
[boxnum] [varchar](50) NOT NULL,
[boxtype] [int] NOT NULL,
[status] [varchar](50) NULL,
[modby] [varchar](50) NULL,
[cominvoice] [varchar](50) NULL,
[corp] [varchar](50) NULL

PS Если кто-нибудь может сказать мне, как создать подсказку, в которой, если boxnum отсутствует в истории boxhum, он предлагает пользователю добавить boxtype и corp, так как это необходимо только для boxnum, которые не были полностью готовы к записи.

Заранее благодарим за любую помощь, которую вы можете оказать мне.

[FormatException: Input string was not in a correct format.]
System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal) +9586043
System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info) +119
System.Convert.ToInt32(String value) +48
Equip.EquipmentMainPage.btnReceiveProcess_Click(Object sender, EventArgs e) in C:\Users\kevin.price\Documents\Visual Studio 2010\Projects\Equip\EquipmentMainPage.aspx.cs:347
System.Web.UI.WebControls.Button.OnClick(EventArgs e) +118
System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument) +112
System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +10
System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +13
System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +36
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +5563

Ответы [ 4 ]

6 голосов
/ 19 августа 2011

Моим лучшим предположением будет то, что ваша проблема в этой строке:

dm.AddParameters(4, "@boxtype", Convert.ToString(BoxType(lines.GetValue(I).ToString())));

в процедуре @boxtype объявлен как int, но я считаю, что эта перегрузка AddParameters сделает ваш параметр типа varchar.Я не знаю, что ваши данные, но, похоже, одно или другое неверно.Я подозреваю, что приведенная выше строка, вероятно, должна быть

dm.AddParameters(4, "@boxtype", Convert.ToInt32(BoxType(lines.GetValue(I).ToString())));

Это зависит от того, что именно возвращает 1007 *.Если это строковое представление типа int, используйте приведенное выше.Если это int, то вам вообще не нужно конвертировать:

dm.AddParameters(4, "@boxtype", BoxType(lines.GetValue(I).ToString()));

Почему я пришел к такому выводу

Я думал, что добавлюобратите внимание на то, как я отладил эту ошибку, чтобы вы могли разобраться для дальнейшего использования.

Сообщение об ошибке «Ошибка преобразования типа данных nvarchar в int» говорит нам, что где-то ожидает int, но получает nvarchar.Nvarchars - это только тип в SQL, поэтому мы знаем, что в SQL должно быть что-то или что-то в вызове базы данных.

Если бы это было проблемой в самой процедуре, вы бы заметили это, когда вытестировали процедуру вдали от остальной части приложения.Это означает, что, должно быть, дело в том, как вызывается процедура.

В этот момент мы смотрим на список параметров и обнаруживаем, что есть один параметр, который является целым числом.Затем мы проверяем это по коду и эй престо, есть наша подозрительная строка ...

0 голосов
/ 19 августа 2011

Исключение, которое вы получаете, указывает на то, что хранимая процедура пытается преобразовать символьное значение, которое не является числом в int.Это исключение исходит из базы данных, а не из вашего кода.

Способ проверить это - деконструировать хранимую процедуру, запустив ее вручную с набором параметров, воспроизводящих проблему.Я думаю, вы обнаружите, что вы получите ошибку в вашем инструменте запросов.Вам нужно запускать запросы вручную, пока вы не выясните, какое строковое значение не является допустимым числом.

0 голосов
/ 19 августа 2011

Мне кажется, ваша хранимая процедура ожидает, что Boxtype будет int. Однако вы настраиваете SqlCommand с параметром @BoxType, который будет строкой - ADO.NET интерпретирует, что параметр @BoxType является строкой типа. Когда он выполняет запрос, он преобразует @BoxType в nvarchar. SQL Server, в свою очередь, попытается преобразовать этот nvarchar в int при выполнении хранимой процедуры. Поскольку SQL-сервер не может этого сделать, это приводит к вашей ошибке.

В основном измените эту строку:

dm.AddParameters(4, "@boxtype",
       Convert.ToString(BoxType(lines.GetValue(I).ToString())));

до

dm.AddParameters(4, "@boxtype", 
       Convert.ToInt32(BoxType(lines.GetValue(I).ToString())));

Конечно, будучи уверенным, что рассматриваемое значение всегда конвертируется в int. :)

0 голосов
/ 19 августа 2011

Я заметил, что вы спросили об этом минуту назад, поэтому я просто опубликую быстрый ответ, но сначала проверим очевидные вещи. Это просто ошибка приведения типа, поэтому проверьте, какие параметры используются для хранимой процедуры. Это может быть то, что дает ключ. Сейчас я прочитаю ваши вещи более тщательно.

Эта строка передается в виде строки, поэтому, возможно, измените ее на int.Parse («числовые строки») или используйте int.TryParse. (Google и MSDN дадут вам приличное руководство по их использованию. Хочу заметить, вы говорите, что вы обделены этим)

dm.AddParameters(4, "@boxtype", Convert.ToString(BoxType(lines.GetValue(I).ToString())));

Но процедура ожидает int.

ALTER PROCEDURE [dbo].[bxReceive]
-- Add the parameters for the stored procedure here
@OP varchar(50), @BatchID varchar(50), @BatchDate varchar(50),
@boxnum varchar(50), 
@boxtype int, 
@status varchar(50), @modby varchar(50), @corp varchar(50), @cominvoice varchar(50) 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...