Грешка при аритметично препълване при преобразуване на израз в тип данни nvarchar

Създавам система за бюро за помощ, но изглежда се натъквам на лек проблем, когато потребителят щракне върху бутон за „предварителна регистрация“ на номера на билета за бюро за помощ, моят скрипт се задейства към SQL Express сървъра, създавайки нов ред -> получава ID на ред -> Използва ID на реда, за да създаде окончателната реф на билета (във формат RAD000001 например за ред 1) този процес изглежда работи добре за мен, докато стигна до номер 9... когато потребителят щракне върху " бутон за създаване на нов номер на билет" (Генериране на номер на билет 10) получавам следната грешка:

Arithmetic overflow error converting expression to data type nvarchar.

Създава реда, но изглежда се проваля при актуализацията (редът е създаден, идентификаторът е върнат и след това рефът е създаден от идентификатора)

Моята SQL таблица изглежда така:

CREATE TABLE [dbo].[tickets](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [ticket_ref] [varchar](15) NULL,
    [details_id] [int] NULL,
    [state] [int] NULL,
    [create_date_Time] [datetime] NOT NULL,
    [details_subject] [varchar](255) NULL,
    [details_main_body] [text] NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

и това е C# кодът зад:

private string Reform_TicketId(string original_ticket_id)
{
    switch (original_ticket_id.Length)
    {
        case 1:
            return "RAD00000" + original_ticket_id.ToString();
        case 2:
            return "RAD0000" + original_ticket_id.ToString();
        case 3:
            return "RAD000" + original_ticket_id.ToString();
        case 4:
            return "RAD00" + original_ticket_id.ToString();
        case 5:
            return "RAD0" + original_ticket_id.ToString();
        case 6:
            return "RAD" + original_ticket_id.ToString();
        default:
            return "ERROR!";
    }
}

protected void DsCreateTicketEntry_Inserted(object sender, SqlDataSourceStatusEventArgs e)
{
    string original_id = e.Command.Parameters["@ticket_id"].Value.ToString();
    string reformed_id = Reform_TicketId(original_id.ToString()).ToString();

    if (original_id != "0")
    {
        //It has returned a value that is a DB ID field and seems correct! lets proceed!
        DsCreateTicketEntry.UpdateParameters["ticket_db_id"].DefaultValue = original_id;
        //DsCreateTicketEntry.UpdateParameters["new_ticket_id"].DefaultValue = reformed_id;
        DsCreateTicketEntry.UpdateParameters["new_ticket_id"].DefaultValue = "RAD000002";
        DsCreateTicketEntry.Update();
        LblTicketOutput.Text = reformed_id;
    }
    else
    {
        //@TODO: Write to the label stating we had problems generating a Ticket ID!
    }
}

protected void btnCreateTicket_Click(object sender, EventArgs e)
{
    DsCreateTicketEntry.Insert();
    btnCreateTicket.Enabled = false;
}

със следните заявки в моя SQLDataSource:

InsertCommand="INSERT INTO tickets(state, create_date_Time) VALUES (1,GETDATE()) SET @ticket_id=SCOPE_IDENTITY();"    
UpdateCommand="UPDATE tickets SET ticket_ref = @new_ticket_id WHERE (id = @ticket_db_id)"

Надяваме се, че някой може да хвърли малко светлина върху това къде греша!? Гледах този код цял ден и той падна малко извън моето ниво на обучение...


person tornup    schedule 16.05.2012    source източник
comment
Току-що забелязах реда: DsCreateTicketEntry.UpdateParameters[new_ticket_id].DefaultValue = RAD000002; Това беше поставено там за отстраняване на грешки, обикновено използвах променливата reformed_id.   -  person tornup    schedule 17.05.2012
comment
Кой ред от код дава тази грешка?   -  person jams    schedule 17.05.2012
comment
здравей @jams това е този ред: DsCreateTicketEntry.Insert();   -  person tornup    schedule 17.05.2012
comment
Вместо да коментирате, че примерният код е грешен, защо не поправите примерния код?   -  person Aaron Bertrand    schedule 17.05.2012
comment
@AaronBertrand Чувствах, че показва, че съм се опитал да отстраня проблема сам, преди да изпълня stackoverflow, и че грешката все още присъства дори с горния код за отстраняване на грешки.   -  person tornup    schedule 17.05.2012
comment
Във вашата InsertCommand задавате параметър @ticket_id с SCOPE_IDENTITY(). Дефиниран ли е някъде този параметър? От тип цяло число (не varchar)?   -  person Steve    schedule 17.05.2012


Отговори (3)


Ще трябва да дефинирате @ticket_id като изходен параметър и може да се нуждаете от точка и запетая преди оператора SET.

Използвайте:

String.Format("RAD{0:d6}", ticket_Id)

за да форматирате номера на вашия билет. Имайте предвид, че в моя пример ticket_id е цяло число.

Като обща препоръка бих избегнал SQLDataSource и този модел на проектиране като цяло. В днешно време има много по-добри и по-елегантни решения за достъп до данни. Разгледайте Entity Framework. EF ще ви накара да работите бързо, без SQL изрази, вградени във вашия код. Можете да генерирате Entity класове от вашата DB или дори да използвате подхода Code First, за да генерирате вашата DB схема от вашите класове.

person saille    schedule 17.05.2012

Не е точно решение на вашия проблем, но може да работи, ако можете да предефинирате таблицата си като:

...

    Id int identity not null,
    Ticket_ref as 'RAD'+replicate('0', 5-len(cast(Id as varchar)))+Cast(Id as Varchar) persisted,
...

бихте изпуснали много редове в ненужен код...

person Val Bakhtin    schedule 16.05.2012

След отговора на Saille, прегледах кода си и забелязах, че там, където декларирах @ticket_id, го декларирах така:

<asp:Parameter DefaultValue="0" Direction="Output" Name="ticket_id" />

След посочване на "DbType=Int32" като:

<asp:Parameter DefaultValue="0" Direction="Output" DbType=Int32 Name="ticket_id" />

Изглеждаше, че всичко работи правилно и проблемът не е разрешен!

Въпреки че не съм 100% сигурен защо това е причинило проблем, може ли някой да ми обясни това, позволявайки ми (и надявам се на други) да разбера защо това направи това, което направи...

PS. Използвам този проект, за да науча общ C#/ASP.net (сесии и т.н.), след като бъде направено, версия 1.5 ще бъде изградена с по-добър слой на база данни (като Entity)... Все още съм малко n00b !

Благодаря за цялата помощ момчета!

Том.

person tornup    schedule 17.05.2012