简体   繁体   English

从应用程序(C#)将数据类型nvarchar转换为int时出错,但独自运行SP时却没有

[英]Getting an error converting data type nvarchar to int from application (C#) but not when running the SP on it's own

My company had contracted a developer to build a new inventory program that would replace the old outdated one. 我的公司已与开发人员签约,以建立一个新的库存程序,该程序将替换旧的过时程序。 Unfortunately for me the developer left before debugging the application and as a result I am stuck trying to figure out 2 issues with my limited knowledge of C# so enough of my sob story here is the issue I am having. 对于我来说不幸的是,开发人员在调试应用程序之前就离开了,结果我被困在试图用有限的C#知识来找出2个问题,所以我的苦闷故事足够多了。

The majority of the application works fine but when trying to receive inventory from our technicians I get an error (SqlException was unhandled by user code- Error converting data tyoe nvarchar to int). 大多数应用程序都可以正常运行,但是当尝试从我们的技术人员处接收清单时,我收到一个错误(用户代码未处理SqlException-将数据类型tyvar nvarchar转换为int时出错)。 I have been staring at the code, tables and stored procedure with no luck finding the problem I hope someone can point out what I am missing here. 我一直在盯着代码,表和存储过程,但是没有运气找到问题,希望有人指出我在这里缺少的东西。 Below is the stack trace, C# coding, stored procedure and tables. 以下是堆栈跟踪,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# code snippit 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);
            }
        }

Stored Procedure 储存程序

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

Tables 桌子

[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 If anyone can tell me how to create a prompt where if boxnum is not in boxhistory it prompts the user to add the boxtype and corp as it's only needed on boxnum's that were not all ready recorded. PS:如果有人可以告诉我如何在boxhistory中没有boxnum的地方创建提示,则会提示用户添加boxtype和corp,因为仅在尚未全部记录的boxnum上才需要。

Thanks in advance for any help you can provide me. 预先感谢您可以为我提供的任何帮助。

[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

My best guess would be that your problem is in this line: 我最好的猜测是,您的问题出在这一行:

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

in the procedure @boxtype is declared as an int but I believe this overload of AddParameters will make your parameter of type varchar. 在过程中@boxtype被声明为int,但是我相信AddParameters的这种重载会使您的参数成为varchar类型。 I don't know what your data is but one or other seems wrong. 我不知道您的数据是什么,但一个或另一个似乎是错误的。 I suspect the above line probably should be 我怀疑上面的线可能应该是

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

It depends on exactly what BoxType(lines.GetValue(I).ToString())) returns. 这完全取决于BoxType(lines.GetValue(I).ToString()))返回什么。 If it is a string representation of an int then use the above. 如果它是int的字符串表示形式,则使用上面的内容。 If it is an int then you don't need the convert at all: 如果它是一个整数,那么您根本不需要转换:

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

Why I came to this conclusion 为什么我得出这个结论

I thought I'd add a note on how I debugged this error so that you can understand for future use. 我以为我会就如何调试此错误添加注释,以便您理解以备将来使用。

The error message "Error converting data type nvarchar to int" tells us that somewhere is expecting an int but receiving an nvarchar. 错误消息“将数据类型nvarchar转换为int时出错”告诉我们某个地方期望有int但接收到nvarchar。 Nvarchars are only a type in sql so we know that there must be either something in the sql or something in the call to the database. Nvarchars只是sql中的一种类型,因此我们知道sql中必须包含某些内容,或者对数据库的调用中必须包含某些内容。

If it was a problem in the procedure itself you would have noticed it when you were testing the procedure away from the rest of the app. 如果程序本身存在问题,则在远离应用程序其余部分进行测试时,您会注意到它。 This means it must have been down to the way the procedure is being called. 这意味着它一定已经被调用了。

At this point we look at the parameter list and find that there is one parameter that is an int. 此时,我们查看参数列表,发现有一个参数是int。 We then check that against the code and hey presto, there's our suspicious looking line... 然后,我们根据代码检查代码,嘿,presto,这是我们可疑的行...

I note you've asked this one minute ago, so I'm just going to post a quick response but check the obvious things first. 我注意到您在一分钟前已经问过这个问题,所以我只想发表快速答复,但请先检查明显的事情。 This is just a type casting error so check what the parameters going to the stored procedure are. 这只是类型转换错误,因此请检查存储过程使用的参数。 It could be that provides the clue. 可能提供了线索。 I'll read through your stuff more thoroughly now. 现在,我将更彻底地阅读您的内容。

This line passes in a string, so maybe change this to int.Parse("numeric strings") or use int.TryParse. 该行传入一个字符串,因此可以将其更改为int.Parse(“ numericstrings”)或使用int.TryParse。 (Google and MSDN will give you decent guides on using these. I note you say you've been lumbered with this) (Google和MSDN将为您提供使用它们的不错的指南。我注意到您说您对此感到不知所措)

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

But the procedure is expecting an int. 但是该过程期待一个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) 

It looks to me like your stored procedure expects Boxtype to be an int. 在我看来,您的存储过程希望Boxtype是一个int。 You are, however, setting up the SqlCommand with a @BoxType parameter that will be a string - ADO.NET will interpret that the @BoxType parameter is type string. 但是,您将使用@BoxType参数设置SqlCommand,该参数将为字符串-ADO.NET将解释@BoxType参数为字符串类型。 When it runs the query, it will convert @BoxType to an nvarchar. 运行查询时,它将@BoxType转换为nvarchar。 SQL Server will in turn attempt to convert that nvarchar to an int when executing the stored procedure. SQL Server将在执行存储过程时尝试将nvarchar转换为int。 Since SQL server can't do this, that's causing your error. 由于SQL Server无法执行此操作,因此导致了您的错误。

Basically, change this line: 基本上,更改此行:

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

to

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

Being sure, of course, that the value in question is always convertible to an int. 当然,请确保所讨论的值始终可以转换为整数。 :) :)

The exception you're getting indicates that the stored procedure is trying to cast a character value that is not a number to int . 您得到的异常表明存储过程正在尝试将不是数字的字符值转换为int This exception is coming from the database, not your code. 此异常来自数据库,而不是您的代码。

The way to test this is to deconstruct the stored procedure by running it manually with a set of parameters that reproduce the problem. 测试此方法的方法是通过使用一组重现该问题的参数手动运行存储过程来解构该存储过程。 I think you'll find that you'll get an error in your query tool. 我认为您会发现查询工具中出现错误。 You need to run the queries manually until you figure out which string value is not a valid number. 您需要手动运行查询,直到找出哪个字符串值不是有效数字为止。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM