Связь между данными веб-формы Combobox и базой данных (SQL Server и ASP.NET) - PullRequest
0 голосов
/ 16 сентября 2011

Название, хотя и длинное, в значительной степени говорит само за себя.

То, что у меня есть, это главная таблица с кучей поддерживающих отношений между таблицами посредством внешних ключей.Для некоторых из внешних таблиц при попытке вставить запись в основную таблицу, где один из внешних ключей не существует, данные будут переданы во внешнюю таблицу, чтобы сначала создать запись, тем самым делая ограничение действительным ипередача ключа к созданной записи обратно в процедуру вставки основной таблицы.

Эти данные поступают из формы в строковой форме, но, естественно, внешний ключ будет int.Процесс будет выглядеть примерно так:

-- ASP.NET Web Form --
Requestor Name:    _____________ (combobox)
Request:           _____________ (dropdownlist)
Date:              _____________ (datepicker)

Это супер упрощенная версия, но предположим, что у нас есть основная таблица с вышеуказанными данными, где оба имени являются внешними ключами таблицы People.Поля имен - это поля со списком с заполненным списком имен, связанных с людьми.Однако, если я хотел ввести человека, которого еще не было в таблице «Люди», процедура должна сначала создать человека, а затем использовать идентификатор из этой новой записи в качестве внешнего ключа в главной таблице, содержащей столбцы для вышеупомянутого.

Я использую SQL Server и ASP.NET с кодом VB.NET.Я некоторое время ломал голову над этим вопросом, как передавать данные (в различных формах, таких как внешний ключ или строка) между веб-сервером и сервером БД, а также где проверять / преобразовывать данные.

Похоже, что введенное имя будет передано в виде идентификатора, если внешний ключ существует, и строки, если нет.

Это моя самая сложная проблема на данный момент, и нетИдея, где еще искать.Я прочитал о сайте Скотта Митчелла и других.

МОЕ РЕШЕНИЕ (?)

Лучшее, что я могу придуматьс - передать пользовательский ввод в виде строки и преобразовать его в int в процедуре T-SQL.Если значение было выбрано из выпадающего списка, оно должно точно соответствовать действительному внешнему ключу.Если он не совпадает, создайте нового человека и верните внешний ключ.Это лучшая практика?

Ответы [ 2 ]

0 голосов
/ 27 января 2012

Вот моя реализация. Я не знаю, лучший ли это, но у меня это сработало. В основном я беру значения из элементов управления; в случае со списком я нуждаюсь в значениях как TextBox, так и DropDownList. Затем я передаю эти значения следующей функции в моем коде:

'This method determines if the name selected already exists in the selection
'  options and if so assigns the corresponding ID value to an object variable,
'  if not it assigns the value of the `TextBox` to the variable.
Protected Function _ValidateValues(ByRef ddl As DropDownList, ByRef cb As TextBox) As Object
    'Ensures the selected value is valid by checking against the entered value in the textbox
    If Not String.IsNullOrEmpty(cb.Text) Then
        If ddl.Items.Count > 0 Then
            If StrComp(cb.Text, ddl.SelectedItem.ToString) = 0 Then
                Return ddl.Items.Item(ddl.SelectedIndex).Value 'Returns the index of dropdown selected name
            End If
        End If
        'This counts the capital letters in the entered value and if fewer than 2
        '  auto capitalizes the first letters. This also allows for project code
        '  names such as "DOORS" and people names such as "Allen McPherson" etc.
        '  Be careful though because if "allen McPherson" is entered, it will NOT
        '  be corrected, though it displays correctly.
        Dim rg As New Regex("[A-Z]")
        Dim mc As MatchCollection = rg.Matches(cb.Text)
        If mc.Count < 2 Then
            Return StrConv(cb.Text, VbStrConv.ProperCase)
        Else : Return cb.Text
        End If
    End If
    'Returns a SQL DB NULL object if an empty string is submitted
    Return DBNull.Value
End Function

Тогда моя хранимая процедура обрабатывает значения примерно так ...

(Простите, если я забыл заменить некоторые значения. Я пытался поймать их все.)

CREATE PROCEDURE spInsertUser
    @User nvarchar(50)    = NULL,
    @Role nvarchar(50)    = NULL,
    @RecordID int output  -- Returned Value
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    -- CHECK IF USER EXISTS
    -- Insert new record to Users table if the requested user doesn't exist
    -- Needed to ensure that the foreign keys are relevant
    IF @User = '' OR @User IS NULL BEGIN SET @User = NULL SET @RecordID = NULL END --Ensures that an empty string cannot be submitted, thereby causing an error.
    ELSE BEGIN
        declare @forename varchar(50), @surname varchar(50)
        declare @uid table (ID int)
        declare @users table (ID smallint, Name nvarchar(50))
        insert into @users
        select ID, Name from Users

        --If the value can be converted into an int, we need go no further.
        BEGIN TRY SET @RecordID = CONVERT(smallint, @User) END TRY
            BEGIN CATCH
                BEGIN TRY --Otherwise, attempt to parse the name
                    Set @User = LTRIM(RTRIM(@User)) --Trim the extra space at the beginning and end. This ensures the following "IF" test will evaluate properly.
                    IF NOT CHARINDEX(' ', @User) > LEN(@User) AND CHARINDEX(' ', @User) > 0 BEGIN -- Confirm First & Last Name exist
                        Set @forename = RTRIM(LEFT(@User, CHARINDEX(' ',@User,0)-1))
                        Set @surname = LTRIM(RIGHT(@User, LEN(@User) - CHARINDEX(' ',@User,0)))
                        Set @User = @forename + ' ' + @surname --Ensure that there is a valid First & Last name
                        IF LEN(@forename) > 1 AND LEN(@surname) > 1 BEGIN -- Confirm First & Last Name exist
                            --First ensure that the User doesn't already exist, and if
                            --  so use their ID, if not insert the new User.
                            IF NOT EXISTS (select Name from @users where Name like @User) BEGIN --Check if the user already exists
                                INSERT INTO Users (Name, Forename, Surname) OUTPUT INSERTED.ID INTO @uid Values (@User, -- If not, insert them
                                    @forename, @surname) --Nicely manicured first, last, and full names
                                SET @RecordID = CONVERT(smallint, (select MAX(ID) from @uid)) END -- Now set the Role to the ID of the new user
                            ELSE BEGIN --Otherwise if the user already exists, set the Role to the ID of that user
                                SET @RecordID = (select ID from @users where Name like @User) END

                            IF NOT EXISTS (select * from rUsersInRoles where UserID = @RecordID) BEGIN
                            --Do some string manipulation to increase the chances of matching the role
                            SET @Role = REPLACE(REPLACE(REPLACE(LTRIM(RTRIM(@Role)), ' ', '%'), '.', '%'), '@', '%') --Trims & replaces spaces & periods with wildcards
                            INSERT INTO rUsersInRoles (UserID, UserRoleID) VALUES
                                (@RecordID, (select top 1 ID from rUserRoles where Role like @Role)) END
                        END
                    END
                END TRY
                BEGIN CATCH END CATCH    
            END CATCH
    END
END

Эта хранимая процедура также относится к случаю пользовательских ролей. Если требуется только более простой случай пользователей, просто удалите пункты, касающиеся проверки и вставки ролей пользователей. :)

0 голосов
/ 16 сентября 2011

Это кажется сложным, потому что это так. Вы должны запачкать руки. Если вам нужна реляционная база данных с поддержкой ACID , то нет никакого магического способа обойти ее.

Реляционные базы данных 101: первичный ключ должен существовать до того, как внешний ключ может быть заполнен (по этой причине разработчики хранилища данных заполняют таблицу измерений перед таблицей фактов). Вам нужно будет разработать логику для проверки того, что первичный ключ существует, вставить и получить ключ, если нет, и просто получить ключ, если существует.

...