以下内容尚未经过全面测试,但应该可以满足您的需求。在下面的示例中,动态创建 WHERE IN 条件时使用参数而不是注入,在这种情况下使用逗号分隔的命令值列表。
完整的工作代码示例可以在以下GitHub repository中找到。
终于SQL
SELECT C.CustomerIdentifier ,
C.CompanyName ,
C.ContactName ,
C.ContactTypeIdentifier ,
FORMAT(C.ModifiedDate, 'MM-dd-yyyy', 'en-US') AS ModifiedDate,
CT.ContactTitle
FROM dbo.Customers AS C
INNER JOIN dbo.ContactType AS CT ON C.ContactTypeIdentifier = CT.ContactTypeIdentifier
WHERE CT.ContactTitle IN (@CTContactTitle0,@CTContactTitle1) AND Req_ID = "R1"
ORDER BY C.CompanyName
创建 WHERE IN 的代码
Imports System.Data.SqlClient
Imports System.Runtime.CompilerServices
Imports System.Text.RegularExpressions
''' <summary>
''' Contains methods to create dynamic WHERE IN conditions on a single field
''' </summary>
''' <remarks>
''' These methods are not meant to handle every single condition, they are
''' for simple IN clauses e.g.
'''
''' WHERE SomeField IN (1,2,3)
''' WHERE SomeField IN ('June','April')
''' WHERE YEAR(SomeField) IN (2008,2007,2018)
''' WHERE SomeField IN ('4-4-1960','9-22-1989')
'''
''' If a function is year that has arguments these methods will not handle
''' them "as is".
'''
''' </remarks>
Public Module SqlWhereInParameterBuilder
''' <summary>
''' Create a SQL SELECT statement which is then passed off to
''' AddParamsToCommand to create a parameter for each value.
''' </summary>
''' <typeparam name="T">SELECT Statement with WHERE condition</typeparam>
''' <param name="partialClause">Base SQL SELECT statement</param>
''' <param name="paramPrefix">WHERE IN field</param>
''' <param name="parameters">Value list for WHERE IN</param>
''' <returns>SELECT Statement with WHERE condition ready to populate values</returns>
Public Function BuildWhereInClause(Of T)(partialClause As String, paramPrefix As String, parameters As IEnumerable(Of T)) As String
paramPrefix = StripFunction(paramPrefix)
Dim parameterNames = parameters.Select(
Function(paramText, paramNumber) $"@{paramPrefix.Replace(".", "")}{paramNumber}").ToArray()
Dim whereInClause = String.Format(partialClause.Trim(), String.Join(",", parameterNames))
Return whereInClause
End Function
''' <summary>
''' Create a parameter for each value in parameters
''' </summary>
''' <typeparam name="T">Command with parameters setup</typeparam>
''' <param name="cmd">Command object</param>
''' <param name="paramPrefix">Field name for the WHERE IN</param>
''' <param name="parameters">Values for the WHERE IN</param>
<Extension>
Public Sub AddParamsToCommand(Of T)(cmd As SqlCommand, paramPrefix As String, parameters As IEnumerable(Of T))
paramPrefix = StripFunction(paramPrefix)
Dim parameterValues = parameters.Select(Function(paramText) paramText).ToArray()
Dim parameterNames() As String = parameterValues.Select(
Function(paramText, paramNumber) $"@{paramPrefix.Replace(".", "")}{paramNumber}").ToArray()
For index As Integer = 0 To parameterNames.Length - 1
cmd.Parameters.AddWithValue(parameterNames(index), parameterValues(index))
Next
'
' Display what a hacker would see
'
If Debugger.IsAttached Then
Console.WriteLine(cmd.CommandText)
End If
End Sub
''' <summary>
''' Used to get a field name from a function e.g. YEAR(ActiveDate)
''' which will return ActiveDate.
''' </summary>
''' <param name="pValue"></param>
''' <returns></returns>
Private Function StripFunction(pValue As String) As String
If pValue.Contains("(") Then
Dim regularExpressionPattern As String = "(?<=\()[^}]*(?=\))"
Dim re As New Regex(regularExpressionPattern)
Return re.Matches(pValue)(0).ToString()
Else
Return pValue
End If
End Function
End Module
这是一个控制台项目(Imports SqlHelpers)中的粗略示例,是上面的一个类项目。
Imports System
Imports System.Data
Imports SqlHelpers
Module Program
Sub Main(args As String())
Dim contacts = New List(Of String) From {"May Jones", "Tim O'Brian"}
Examples.ReadCustomersByContactType(contacts)
End Sub
End Module
Public Class Examples
Public Shared Function ReadCustomersByContactType(pContactTitleList As List(Of String)) As DataTable
'mHasException = False
' field which the WHERE IN will use
Dim parameterPrefix = "CT.ContactTitle"
' Base SELECT Statement
Dim selectStatement =
<SQL>
SELECT C.CustomerIdentifier ,
C.CompanyName ,
C.ContactName ,
C.ContactTypeIdentifier ,
FORMAT(C.ModifiedDate, 'MM-dd-yyyy', 'en-US') AS ModifiedDate,
CT.ContactTitle
FROM dbo.Customers AS C
INNER JOIN dbo.ContactType AS CT ON C.ContactTypeIdentifier = CT.ContactTypeIdentifier
WHERE <%= parameterPrefix %> IN ({0}) AND Req_ID = "R1"
ORDER BY C.CompanyName
</SQL>.Value
' Builds the SELECT statement minus values
Dim CommandText = BuildWhereInClause(selectStatement, parameterPrefix, pContactTitleList)
Dim dt As New DataTable
Using cn As New SqlClient.SqlConnection
Using cmd As New SqlClient.SqlCommand
cmd.CommandText = CommandText
'
' Add values for command parameters
'
cmd.AddParamsToCommand(parameterPrefix, pContactTitleList)
Console.WriteLine()
Try
'cn.Open()
'dt.Load(cmd.ExecuteReader)
Catch ex As Exception
'mHasException = True
'mLastException = ex
End Try
End Using
End Using
Return dt
End Function
End Class
如果需要,在 Git 存储库中还有一个自定义文本框。