Webform Combobox 数据和数据库之间的链接(SQL Server 和 ASP.NET)

发布于 2024-12-04 23:52:19 字数 1110 浏览 0 评论 0原文

标题虽然很长,但几乎说明了一切。

我拥有的是一个主表,其中有一堆通过外键支持的表关系。对于一些外部表,当尝试将一条记录插入到其中一个外键不存在的主表中时,数据将被传递到外部表以首​​先创建记录,从而使约束有效并且将创建的记录的键传递回主表的插入过程。

该数据来自字符串形式的表单,但外键自然会是 int。该过程看起来像这样:

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

这是一个超级简化的版本,但假设我们有一个包含上述数据的主表,其中两个名称都是 People 表的外键。 姓名字段是组合框,其中包含链接到人员的姓名填充列表。但是,如果我想输入 People 表中尚不存在的人员,则该过程应首先创建该人员,然后使用该新记录中的 ID 作为包含上述列的 Master 表中的外键。

我正在使用 SQL Server 和 ASP.NET 以及 VB.NET 代码隐藏。我已经在这个问题上摸索了一段时间了,如何在 Web 服务器和数据库服务器之间传递数据(以不同的形式,如外键或字符串),以及在哪里验证/转换数据。

如果外键存在,输入的名称似乎将作为 ID 传递,如果不存在,则作为字符串传递。

这是迄今为止我最困惑的问题,不知道还能去哪里寻找。我已经阅读了 Scott Mitchell 的 网站,并且其他的。

我的解决方案(?)

我能想到的最好办法是将用户的用户输入作为字符串传递,并在 T-SQL 过程中将其转换为 int。如果从下拉列表中选择该值,则它应该与有效的外键精确匹配。如果不匹配,则创建一个新的 Person 并返回外键。这是最佳实践吗?

The title, while long, pretty much says it all.

What I have is a master table with a bunch of supporting table relations through foreign keys. For a few of the foreign tables, upon attempting to insert a record into the master table where one of the foreign keys doesn't exist, the data would be passed to the foreign table to create the record first, thereby making the constraint valid and passing the key to the created record back to the insert procedure of the master table.

This data comes from a form in String form, but naturally the foreign key will be an int. The process would look something like this:

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

This is a super simplified version, but assume we have a master table with the above data, where both names are foreign keys to a People table. The name fields are comboboxes with a populated list of names linking to People. However, if I wanted to enter a person who didn't yet exist in the People table, the procedure should first create the Person, then use the ID from that new record as the foreign key in the Master table containing columns for the above.

I'm using SQL Server and ASP.NET with VB.NET codebehind. I've been scratching my head over this one for awhile, how to pass data (in different forms such as a foreign key or string) between the web server and DB server, as well as where to validate / transform the data.

It seems the entered name will be passed as an ID if the foreign key exists, and a String if not.

This is my most perplexing problem so far, and no idea where else to look. I've read up on Scott Mitchell's site and others.

MY SOLUTION (?)

The best I can come up with is to pass the user input from the user as a string and convert it to int in the T-SQL procedure. If the value was selected from the drop down, it should match precisely with a valid foreign key. If it doesn't match, then create a new Person and return a foreign key. Is this best practice?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

跨年 2024-12-11 23:52:19

这看起来很复杂,因为事实确实如此。你必须亲自动手。如果您需要一个支持 ACID 支持的关系数据库,则没有自动神奇的方法可以绕过它。

关系数据库101:在填充外键之前主键必须存在(这就是数据仓库开发人员在事实表之前填充维度表的原因)。您必须设计逻辑来验证主键是否存在,如果不存在则插入并获取键,如果存在则获取键。

This seems complicated because it is. You have to get your hands dirty. If you need a relational database with ACID support, there's no auto-magical way of getting around it.

Relational databases 101: The primary key must exist before the foreign key can be populated (This is the reason why data warehouse developers populate the dimension table before the fact table). You'll have to design the logic to validate that the primary key exists, insert and get the key if not, and just get the key if exists.

泛泛之交 2024-12-11 23:52:19

这是我的实现。我不知道这是否是最好的,但它对我来说效果很好。基本上我从控件中获取值;对于组合框,我需要来自 TextBoxDropDownList 的值。然后,我将这些值传递给代码隐藏中的以下函数:

'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

这个存储过程也处理用户角色的情况。如果只需要更简单的用户情况,只需删除处理用户角色检查和插入的子句即可。 :)

Here's my implementation. I don't know if it's the best, but it worked well for me. Basically I take the values from the controls; in the case of the combobox I need the values from both the TextBox and DropDownList. I then pass those values to the following function in my codebehind:

'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

Then my stored procedure handles the values something like so...

(Forgive me if I neglected to replace some of the values. I tried to catch them all.)

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

This stored procedure deals with the case of User Roles as well. If the more simple case of Users only is needed, simply remove the clauses dealing with the checking and insertion of User Roles. :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文