Public Shared Function SQL查询问题:WHERE子句无法访问DDL控件及类机制咨询
问题分析与解决
先搞懂Public Shared函数的核心逻辑
Public Shared(VB中的共享成员)属于类本身,而非类的某个具体实例:
- 调用时无需创建类的对象,直接用
类名.方法名()即可执行 - 它只能访问类的Shared成员,无法访问实例级成员(比如你的
ddldropdown控件——每个页面实例都有专属的控件实例,Shared方法不知道该访问哪一个) - 所有实例共享同一个Shared成员的内存空间,适合做不依赖实例状态的通用逻辑(比如数据访问、工具方法)
你的代码问题出在哪
HEvents是Shared函数,但它调用的GetCalId是实例级函数,Shared方法不能直接调用非Shared方法- 就算把
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
相关产品推荐
相关产品推荐

