繁体   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

我的公司已与开发人员签约,以建立一个新的库存程序,该程序将替换旧的过时程序。 对于我来说不幸的是,开发人员在调试应用程序之前就离开了,结果我被困在试图用有限的C#知识来找出2个问题,所以我的苦闷故事足够多了。

大多数应用程序都可以正常运行,但是当尝试从我们的技术人员处接收清单时,我收到一个错误(用户代码未处理SqlException-将数据类型tyvar 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:如果有人可以告诉我如何在boxhistory中没有boxnum的地方创建提示,则会提示用户添加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

我最好的猜测是,您的问题出在这一行:

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())));

这完全取决于BoxType(lines.GetValue(I).ToString()))返回什么。 如果它是int的字符串表示形式,则使用上面的内容。 如果它是一个整数,那么您根本不需要转换:

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

为什么我得出这个结论

我以为我会就如何调试此错误添加注释,以便您理解以备将来使用。

错误消息“将数据类型nvarchar转换为int时出错”告诉我们某个地方期望有int但接收到nvarchar。 Nvarchars只是sql中的一种类型,因此我们知道sql中必须包含某些内容,或者对数据库的调用中必须包含某些内容。

如果程序本身存在问题,则在远离应用程序其余部分进行测试时,您会注意到它。 这意味着它一定已经被调用了。

此时,我们查看参数列表,发现有一个参数是int。 然后,我们根据代码检查代码,嘿,presto,这是我们可疑的行...

我注意到您在一分钟前已经问过这个问题,所以我只想发表快速答复,但请先检查明显的事情。 这只是类型转换错误,因此请检查存储过程使用的参数。 可能提供了线索。 现在,我将更彻底地阅读您的内容。

该行传入一个字符串,因此可以将其更改为int.Parse(“ numericstrings”)或使用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) 

在我看来,您的存储过程希望Boxtype是一个int。 但是,您将使用@BoxType参数设置SqlCommand,该参数将为字符串-ADO.NET将解释@BoxType参数为字符串类型。 运行查询时,它将@BoxType转换为nvarchar。 SQL Server将在执行存储过程时尝试将nvarchar转换为int。 由于SQL Server无法执行此操作,因此导致了您的错误。

基本上,更改此行:

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

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

当然,请确保所讨论的值始终可以转换为整数。 :)

您得到的异常表明存储过程正在尝试将不是数字的字符值转换为int 此异常来自数据库,而不是您的代码。

测试此方法的方法是通过使用一组重现该问题的参数手动运行存储过程来解构该存储过程。 我认为您会发现查询工具中出现错误。 您需要手动运行查询,直到找出哪个字符串值不是有效数字为止。

暂无
暂无

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

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