Ошибка арифметического переполнения при преобразовании выражения в тип данных nvarchar

Я создаю систему службы поддержки, но, похоже, столкнулся с небольшой проблемой: когда пользователь нажимает кнопку, чтобы «предварительно зарегистрировать» номер билета службы поддержки, мой скрипт срабатывает на сервере SQL Express, создавая новую строку -> получает идентификатор строки -> использует идентификатор строки для создания окончательной ссылки на билет (в формате 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]

и это код С#:

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; Это было помещено туда для отладки, обычно я использовал реформированную_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 из своей БД или даже использовать подход Code First для создания схемы БД из ваших классов.

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

После ответа Сайля я просмотрел свой код и заметил, что там, где я объявил @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