SQL Server 中的存储过程未使用 VB.Net 编码填充 ASP.Net 下拉列表

Posted

技术标签:

【中文标题】SQL Server 中的存储过程未使用 VB.Net 编码填充 ASP.Net 下拉列表【英文标题】:Stored Procedure from SQL Server is not filling ASP.Net dropdown using VB.Net coding 【发布时间】:2022-01-15 13:23:37 【问题描述】:

情况:

我有一个使用两个表单视图的预构建表单。一种用于取货,一种用于送货。由于客户要求,表格不能更改。整个表单和表单视图使用 WizardStep 过程。 每一方都使用相同的字段使用相同的存储过程预先填写客户公司名称和相关数据,例如取件名称、地址、城市、州等以及交货信息。

存储过程将名称和地址 1 的连接显示为 FullName 和 ClientSubCtr。 ClientSubCtr 是一个 int 字段。此 id 用于将正确的数据填充到每个下拉列表中。

下拉列表不在 FormView 内,位于 form 标签下。

通过<asp:SqlDataSource> 标记测试连接时,配置数据源中的一切正常,并使用适当的参数返回数据。匹配客户端数据的连接对存储过程中使用的表使用基本选择。我尝试对数据使用不同的存储过程,但也没有成功。我现在在本地使用 SQL Server Express。

我尝试禁用asp:SqlDataSource 并仅使用来自page_load 的数据库连接,但没有成功。我已将其注释掉,因为我仍在尝试不同的事情。我可能错过了一些连接到下拉列表的语法。

    'This did not work
    'Using conn As New SqlConnection(connect)
    '    strSQL = "SELECT ClientSubCtr,CONCAT(Name,Address1) AS FullName 'FROM tblClientsSub"
    '    strSQL = strSQL & " WHERE Account ='" & sessAccount & "'"
    '    strSQL = strSQL & " ORDER BY FullName ASC"
    '    conn.Open()

    '    Using cmd As New SqlCommand(strSQL, conn)
    '        cmd.Parameters.AddWithValue("@Account", sessAccount)
    '        cmd.CommandText = strSQL
    '        cmd.ExecuteNonQuery()
    '        Dim dr As SqlDataReader = cmd.ExecuteReader()
    '        If dr.HasRows Then
    '            Do While (dr.Read())
    '                ClientSubCtr = dr.GetValue(0)
    '                FullName = dr.GetValue(1)
    '                s1_cboAcct.DataTextField = FullName
    '                s1_cboAcct.DataValueField = ClientSubCtr
    '                s1_cboAcct.DataBind() 

'修正后的数据绑定仍然不起作用 ' 环形 ' 别的 ' 博士关闭() '结束如果

    '    End Using
    'End Using

附加信息:在使用它之前,我有两个预渲染功能。一个用于取件和交付,它填写了我的客户所说的 Docket。它显示了在初始加载时或通过下拉列表中的 Selected Change 预填充的信息,以及客户端手动添加或更改某些内容的位置,从而将正确的信息发送到数据库以供最终下载。

注意:这最初是为了将 OLEDB ACE 连接到我的客户 Go Daddy 帐户而编写的。 Go Daddy 将站点移至新服务器,将不再支持 ACE 12.0。我们恳求他们改变这一点。因此,迁移到 SQL Server。

当我得到我认为正在加载的数据时,我在此标签上的预渲染中遇到错误。我特意注释掉了所有的预渲染,以查看返回的错误信息。没有错误返回,一般表单返回显示下拉但没有数据,并且 FormView 中的字段看不到。换句话说,甚至标签都没有显示。我检查了所有asp:sqldatasource 设置。

' If IsNothing("txtcboAcct.Text") Then 
'lblDocketPUName.Text = "" 
(I've tried using Request.form here, but data isn't loaded so I get nothing.) and commented out the If Else End If
        '    Else
        '        lblDocketPUName.Text = CType(frmViewPUClient.FindControl("txtcboAcct"), TextBox).Text 
(This is where I get an error where the object is not found because neither the data for the dropdown is loading or the data for the forms.)

        '    End If

我知道这需要消化很多,但我完全不明白为什么使用 OLEDB 和 Access 2007 可以完美地工作,但是当切换到 SQL Server 和名称相同的确切表时,它却没有。任何关于为什么存储过程不会填写下拉列表或者为什么我在 page_load 中的代码也不会填写下拉列表的任何见解都会有所帮助。我已更新所有参数以使用 @ 符号。

这是存储过程:

'ALTER PROCEDURE [dbo].[qryFullNameAddr] 
'@Account nvarchar(10) OUTPUT
'AS
'   -- Add the parameters for the stored procedure here
'DECLARE @ClientSubCtr int
'DECLARE @Name nvarchar(50)
'DECLARE @Address1 nvarchar(125)
'DECLARE @FullName nvarchar(255)


'BEGIN
'   -- SET NOCOUNT ON added to prevent extra result sets from
'   -- interfering with SELECT statements.
'   SET NOCOUNT ON;

'    /*Write statements for procedure here */

'SELECT ClientSubCtr,CONCAT(Name,Address1) AS FullName
'FROM tblClientsSub 
'WHERE @Account=@Account
'ORDER BY FULLNAME, ADDRESS1 ASC
'end

【问题讨论】:

对于某些编码部分没有正确显示,我深表歉意,这是我的第一篇文章,所以是发帖的新手。我想当我引用它正确显示的一些代码时。生活和学习。 大家好消息。我从头开始。我尝试使用的表格没有任何效果。所以我检索了我的 OleDB 的一个新副本,将所有内容都更改为 SQL。没有使用存储过程,但原始表和现在一切正常。为什么我等了这么久才这样做,我不知道。事后看来是 20/20。 【参考方案1】:

好吧,可以这么说,首先我会倒车。

我将创建一个空白的新测试网页。放入一个下拉列表,然后让它工作。

接下来:

您无需循环访问下拉列表。您可以为下拉列表提供表格。该表可以是查询,也可以是存储过程。

所以,首先,让我们在下拉列表中显示一个酒店列表。和大多数下拉菜单一样,通常有两列是隐藏的“id”或行的“PK”,然后是显示文本。

所以,我们的空白页面,我们放入一个下拉列表。像这样说:

<form id="form1" runat="server">
    <div>
        <asp:DropDownList ID="DropDownList1" runat="server" 
            DataTextField="HotelName" 
            DataValueField="ID" Height="22px" Width="219px">
        </asp:DropDownList>
    </div>
</form>

现在要填写的代码 - 并且如前所述,始终只在第一页加载时加载 - 即 PostBack = false - (打破该规则,您甚至无法制作一个正常工作的网页)。

好的,现在我们的代码是这样的:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    If Not IsPostBack Then
        LoadData
    End If

End Sub

Sub LoadData()

    Using con As New SqlConnection(My.Settings.TEST4)

        Dim strSQL As String = "SELECT ID, HotelName from tblHotels ORDER BY HotelName"
        Using cmdSQL As SqlCommand = New SqlCommand(strSQL, con)

            con.Open()
            Dim rstData As New DataTable
            rstData.Load(cmdSQL.ExecuteReader)
            DropDownList1.DataSource = rstData
            DropDownList1.DataBind()
            DropDownList1.Items.Insert(0, New ListItem("", "")) ' optional blank starting select

        End Using

    End Using

End Sub

就是这样!!!

另外,不知道为什么这么多代码示例在代码中设置了DataTextField和DataValue字段?为什么????只需使用属性表 - 几乎不需要将这些东西放在代码端 - 特别是当属性表可以为您完成时!!!

下一个?好吧,SO 上的每个人都在讨论如何在此类代码中使用参数来代替串联字符串。这是正确的,但是如果您使用参数进行编码,那么您可以经常减少代码,并且无论如何都要清理您的 sql。

您可以删除文本('引号')和数字(不带引号)来代替凌乱的 sql 字符串,这甚至更适合日期。

所以这个好处几乎和 sql 注入问题一样大。 (公平地说,您注意到了一个存储过程,但它不起作用,所以很明显您决定在这里尝试任何东西 - 我明白这种方法)。

那么,你的代码片段?我会这样编码:

    Dim strSQL As String =
        "SELECT ClientSubCtr,CONCAT(Name, Address1) AS FullName FROM tblClientsSub " &
        "WHERE Account = @Acc " &
        "ORDER BY FullName ASC"

    Using conn As New SqlConnection(My.Settings.TEST4)
        Using cmdSQL As New SqlCommand(strSQL, conn)
            cmdSQL.Parameters.Add("@Acc", SqlDbType.NVarChar).Value = sessAccount
            conn.Open()
            s1_cboAcct.DataSource = cmdSQL.ExecuteReader
            s1_cboAcct.DataBind()
        End Using
    End Using

现在是不是更具可读性?

实际上是剪切 + 粘贴您的代码?

我注意到了这一点: SELECT ClientSubCtr,CONCAT(Name,Address1) AS FullName 'FROM

等等? FROM 前面的 ' 是什么???你有一个流浪',不是吗?

也许那是代码剪切 + 粘贴错误,也许不是。但真正的意义是什么?

通过使用参数,我们可以对单引号、双引号和所有爵士乐进行核对。

换句话说,当然,由于 sql 注入的原因,避免值的字符串连接很重要,但真正更有价值的是我们不必为所有这些引号和东西而烦恼。结果是很难错过或搞砸!!!

另一个问题当然是使用上面的参数? 好吧,我们得到了情报。如果我还有更多,那么在 VS 中我只需按 ctrl-d 即可复制该行。实际上,如果我尝试将这些值直接引入 sql 中,我实际上会键入更少的代码!!!想象一下 - 更容易阅读,甚至更少的代码输入!!! - 所有这些都相当于更不容易出错的代码。我的意思是,缺少一个引号,例如 ' 还是一个额外的引号?你有麻烦了,会浪费时间的!!

您还注意到,我什至没有在 DataTable 中使用阅读器,只是将阅读器结果直接推入组合框 - 节省更多代码!!!!

但是,虽然下拉列表、列表视图、网格视图(以及更多)都可以像我一样接受 DataSource 作为 cmdSQL.ExecuteReader?

我仍然强烈建议您将我的第一个版本用于网格/列表视图等(这是一个巨大的原因!!!)。 (如果您为gridview提供阅读器,则数据寻呼机不起作用,但是它们可以正常工作的表格以及数据绑定事件(不常用于组合框,但非常常用于网格通常需要数据源-因此这个组合?当然,你可以省去两行额外的代码(创建一个 DataTable 并加载它)。但是对于 gridview,不要使用我上面使用的那种很酷的捷径,将阅读器直接输入到网格或列表视图中- 但对于连击,完美无缺。

所以,有了上面,在运行上面的代码之后,我们就有了:

如前所述,如果您确实测试或决定加载组合框,并且不使用放入标记中的 DataSoruce 控件(我不太喜欢这些东西),那么请确保您只放置在 If Not IsPostBack 代码存根中调用此类控件的加载。永远不要不遵守这条规则。

再次重申:永远不要不遵守这条规则。

为什么?

因为任何其他按钮或您将放置在该页面上的任何其他东西都可能需要进行回发(即使是几个简单的按钮)。所以,如果你说选择一个组合框,填写一些其他的东西,然后有一些按钮(和一个按钮点击事件,后面有代码)?

好吧,请记住,页面加载总是会触发每个回发!!!

因此,如果您的代码重新加载说组合框,那么它将破坏用户对该组合(或网格或其他任何东西!!!)的任何现有选择。因此,您必须以一种能够“承担”、“工作”和“生存”回发的方式编写代码。因此,您加载控件应该只需要一次,并且在第一页加载 - 因此我对遵循这个简单规则的重要性进行了很长的叙述。

【讨论】:

您看到的单引号来自后面代码中的注释。我在发布之前没有删除它们。第一次发帖,所以还在学习规则。我很欣赏这些信息,但我不需要讲座。 我正在尝试使用数据表加载示例与我当前的数据的一个建议,并且我正在尝试解决 SQL Server 想要 @Account 的问题,即使我已经指定了它。我可以在一个新项目中测试它,只需一个下拉菜单。您知道表单中使用的向导步骤是否会干扰人群,即使当前下拉菜单位于表单下方而不是 formView。

以上是关于SQL Server 中的存储过程未使用 VB.Net 编码填充 ASP.Net 下拉列表的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server存储过程插入长字符串时出错:字符串后引号未闭合

从视图调用时未插入表的存储过程 - SQL Server 2014

Sql Server中的存储过程

SQL Server 存储过程

SQL Server 存储过程

SQL Server 存储过程