You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Public Shared Function SQL查询问题:WHERE子句无法访问DDL控件及类机制咨询

问题分析与解决

先搞懂Public Shared函数的核心逻辑

Public Shared(VB中的共享成员)属于类本身,而非类的某个具体实例:

  • 调用时无需创建类的对象,直接用类名.方法名()即可执行
  • 它只能访问类的Shared成员,无法访问实例级成员(比如你的ddldropdown控件——每个页面实例都有专属的控件实例,Shared方法不知道该访问哪一个)
  • 所有实例共享同一个Shared成员的内存空间,适合做不依赖实例状态的通用逻辑(比如数据访问、工具方法)

你的代码问题出在哪

  1. HEvents是Shared函数,但它调用的GetCalId是实例级函数,Shared方法不能直接调用非Shared方法
  2. 就算把GetCalId改成Shared,它也无法访问ddldropdown——这个控件是页面实例的专属成员,Shared方法没有权限访问

解决方案(推荐最优解)

把CalId作为参数传给HEvents方法,彻底解耦UI控件和数据访问逻辑,同时修复SQL注入风险:

1. 修改Shared函数,接收CalId参数并使用参数化查询

Public Shared Function HEvents(calId As String) As List(Of [Events])
    Dim events As List(Of [Events]) = New List(Of [Events])()
    Dim constr As String = ConfigurationManager.ConnectionStrings("USC").ConnectionString
    ' 使用参数化查询,避免SQL注入
    Dim query As String = "SELECT * From Cal WHERE CalId = @CalId " &
                          "UNION ALL " &
                          "Select 0 As EventId, Description As EventName," &
                          "Format((CAST(Convert(DateTimeOffset, HolidayDate) As datetime)), 'd', 'en-US') AS StartDate," &
                          "Format((CAST(Convert(DateTimeOffset, HolidayDate) As datetime)), 'd', 'en-US') AS EndDate," &
                          "'Red' AS Color," &
                          "'White' AS TextColor," &
                          "'12:00 AM' AS StartTime," &
                          "'11:59 PM' AS EndTime " &
                          "From [Darkside].[USC].[dbo].[Holidays]"

    ' 完整的数据库操作逻辑(补充原代码缺失部分)
    Using conn As New SqlConnection(constr)
        Using cmd As New SqlCommand(query, conn)
            ' 添加参数,避免SQL注入
            cmd.Parameters.AddWithValue("@CalId", calId)
            conn.Open()
            Using reader As SqlDataReader = cmd.ExecuteReader()
                While reader.Read()
                    ' 实例化Events对象并填充属性
                    Dim ev As New [Events]()
                    ' 根据你的Events类结构填充,示例:
                    ' ev.EventId = reader.GetInt32(reader.GetOrdinal("EventId"))
                    ' ev.EventName = reader.GetString(reader.GetOrdinal("EventName"))
                    events.Add(ev)
                End While
            End Using
        End Using
    End Using
    Return events
End Function

2. 在页面代码中调用该方法,传入下拉框的值

' 比如在页面加载、按钮点击等事件中调用
Dim selectedCalId As String = ddldropdown.SelectedValue
Dim eventList As List(Of [Events]) = 你的类名.HEvents(selectedCalId)

不推荐的方案(耦合度高,仅作了解)

如果非要在Shared方法中直接获取控件值,可以通过HttpContext.Current获取当前页面,但这种方法容易出错(比如控件在容器内时找不到),且耦合UI和数据层:

Public Shared Function GetCalId() As String
    Dim currentPage As Page = TryCast(HttpContext.Current.Handler, Page)
    If currentPage IsNot Nothing Then
        Dim dropdown As DropDownList = TryCast(currentPage.FindControl("ddldropdown"), DropDownList)
        Return dropdown?.SelectedValue
    End If
    Return String.Empty
End Function

关键提醒

原代码直接拼接SQL字符串,存在严重的SQL注入风险,必须使用参数化查询(上面的最优解已经修复了这个问题),否则攻击者可以通过构造恶意值篡改你的数据库。

内容的提问来源于stack exchange,提问作者Mr.Skellington

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 17:22:51