2011-08-19 7 views
5

Moja firma zleciła programistce utworzenie nowego programu inwentaryzacji, który zastąpiłby stary przestarzały. Niestety dla mnie deweloper wyszedł z debugowania aplikacji, w wyniku czego utknąłem próbując wymyślić 2 problemy z moją ograniczoną znajomością języka C#, więc wystarczająco dużo mojej łzawej historii tutaj jest kwestią, którą mam.Uzyskiwanie błędu podczas konwersji typu danych nvarchar na int z aplikacji (C#), ale nie podczas uruchamiania dodatku SP na komputerze własnym

Większość aplikacji działa dobrze, ale przy próbie otrzymania ekwipunku od naszych techników pojawia się błąd (wyjątek SqlException nie był obsługiwany przez kod użytkownika - Błąd konwersji danych tyoe nvarchar na int). Patrzyłem na kod, tabele i procedurę przechowywaną bez problemu znajdując problem Mam nadzieję, że ktoś może wskazać, czego tu brakuje. Poniżej znajduje się ślad stosu, kodowanie C#, procedura składowana i tabele.

[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# kod snippit

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

przechowywane Procedura

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 

Tabele

[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 

P.S. Jeśli ktokolwiek może mi powiedzieć, jak utworzyć monit, w przypadku gdy boxnum nie znajduje się w boxhistorii, to prosi użytkownika o dodanie boxsupe i corp, ponieważ jest to potrzebne tylko w boxnum, które nie były wszystkie gotowe do nagrania.

Z góry dziękuję za wszelką pomoc, jaką możesz mi zapewnić.

[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 
+0

Czy parametr @boxtype parametru [bxReceive] oczekuje znaku int i kod przekazuje ciąg znaków? – JohnD

Odpowiedz

6

Mój najlepszy przypuszczenie byłoby, że problem jest w tym wierszu:

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

w @boxtype procedury jest zadeklarowana jako int, ale wierzę, że to przeciążenie AddParameters sprawi, że parametr typu varchar. Nie wiem, jakie są twoje dane, ale jedno lub drugie wydaje się błędne. Podejrzewam, że powyższa linia prawdopodobnie powinien być

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

To zależy od tego co dokładnie BoxType(lines.GetValue(I).ToString())) zyski. Jeśli jest to ciąg znaków reprezentujący int, użyj powyższego.Jeśli jest to int wtedy nie trzeba się nawrócił na wszystkich:

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

Dlaczego doszedłem do tego wniosku

myślałem, że dodać notatkę o tym, jak ja debugowany ten błąd tak które możesz zrozumieć na przyszłość.

Komunikat o błędzie "Błąd konwersji typu danych nvarchar na int" mówi nam, że gdzieś oczekuje int, ale odbiera nvarchar. Nvarchars to tylko typ sql, więc wiemy, że musi być coś w sql lub coś w wywołaniu do bazy danych.

Jeśli był to problem w samej procedurze, zauważyłbyś to podczas testowania procedury z dala od reszty aplikacji. Oznacza to, że musiało to wynikać ze sposobu, w jaki procedura jest wywoływana.

W tym momencie patrzymy na listę parametrów i stwierdzamy, że istnieje jeden parametr, który jest int. Sprawdzamy to pod kodem i hej presto, tam jest nasza podejrzanie wyglądająca linia ...

+0

Dziękuję za odpowiedź Nie zauważyłem, że jest on konwertowany na ciąg znaków i patrząc dalej w kodzie Widzę, gdzie on wyciąga go ze stolika jako ciąg Zamierzam zmienić kod i przetestować go, mam nadzieję, że będzie rozwiązać problem. Dam ci znać, jak to działa. – Kprice84

+0

To jest fajne. Jak wskazywali inni, komunikat o błędzie wskazywał nam bardziej doświadczonych we właściwym miejscu. Właściwie dodam notatkę do mojej odpowiedzi wyjaśniającą, jak znalazłem błąd, abyś mógł zrozumieć nieco więcej, jak doszłam do powyższej odpowiedzi. :) – Chris

+0

Czy sprawdziłeś, co właściwie wraca z tego? Błąd wskazuje, że bez względu na napis, że nie można go przekonwertować na liczbę całkowitą. Możliwe, że może zwrócić pusty łańcuch, w którym to przypadku nie będzie w stanie przetworzyć go jako int. W takim przypadku możesz lepiej przekazać varchar do bazy danych i pozwolić, aby martwił się o parsowanie go i wprowadzanie ustawień domyślnych, jeśli to konieczne. – Chris

0

Przypominam, że już minutę temu zapytałeś, więc zamierzam opublikować szybką odpowiedź, ale najpierw sprawdź oczywiste rzeczy. To jest tylko błąd rzutowania typu, więc sprawdź, jakie parametry przechodzą do procedury przechowywanej. To może stanowić wskazówkę. Przeczytam teraz twoje rzeczy dokładniej.

Ta linia przechodzi w łańcuch, więc może zmienić to na int.Parse ("ciągi liczbowe") lub użyć int.TryParse. (Google i MSDN daje przyzwoite przewodniki na temat korzystania z nich. I pamiętać, mówisz, że już ociężale z tym)

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

Ale procedura oczekuje 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) 
0

Wygląda na to, że Twoja procedura składowana oczekuje, że Boxtype będzie int. Jednak konfigurujesz SqlCommand z parametrem @BoxType, który będzie ciągiem znaków - ADO.NET zinterpretuje, że parametr @BoxType jest łańcuchem typu. Gdy uruchomi zapytanie, skonwertuje @BoxType na nvarchar. SQL Server spróbuje z kolei przekonwertować ten nvarchar na int podczas wykonywania procedury przechowywanej. Ponieważ serwer SQL nie może tego zrobić, powoduje to błąd.

Zasadniczo zmienić tę linię:

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

do

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

Będąc pewny, oczywiście, że wartość w pytaniu zawsze jest wymienialna do int. :)

0

Wyjątek, który otrzymujesz, wskazuje, że procedura składowana próbuje przesłać wartość znaku, która nie jest liczbą do int. Ten wyjątek pochodzi z bazy danych, a nie z twojego kodu.

Aby to przetestować, należy zdekonstruować procedurę przechowywaną, uruchamiając ją ręcznie za pomocą zestawu parametrów odtwarzających problem. Wydaje mi się, że zauważysz błąd w narzędziu do wysyłania zapytań. Musisz ręcznie uruchamiać kwerendy, aby dowiedzieć się, która wartość ciągu nie jest poprawną liczbą.

Powiązane problemy