我個人認爲你還是得太多試圖減少一些不需要減少。你可能便獨自離開存儲過程的參數,或者試圖創造一些基類和輔助功能,可以附加組參數的命令對象更好。
不過,他這樣說,我會拋出一個解決你的問題在那裏,看看它是否適合您的需要:
我建議使用T-SQL用戶定義類型。創建一個或多個類型。也許一個用於日期範圍,另一個用於分頁和排序。我使用類似的過程將多行數據傳遞給存儲過程。 (這些代碼中的一些可能需要稍微調整,因爲我只是修改了一些我已經編寫的代碼,並且在一段時間內我還沒有與DataTable字段一起工作。)
最終,所有這一切縮短應用程序方法和匹配存儲過程中的參數列表。存儲過程將負責提取或連接表變量中的信息。下面列出的類提供了在.NET應用程序端強制輸入這些參數的功能。
if not exists (select * from INFORMATION_SCHEMA.DOMAINS where DOMAIN_SCHEMA = 'dbo' and DOMAIN_NAME = 'DateRange' and DATA_TYPE = 'table type')
begin
create type dbo.DateRange as table
(
StartDate datetime2 null
,EndDate datetime2 null
)
end
go
if not exists (select * from INFORMATION_SCHEMA.DOMAINS where DOMAIN_SCHEMA = 'dbo' and DOMAIN_NAME = 'Paging' and DATA_TYPE = 'table type')
begin
create type dbo.Paging as table
(
PageNumber int null
,PageSize int null
,SortField sysname null
,SortDirection varchar(4) null
)
end
go
的SQL用戶定義的類型可被表示在.NET應用程序作爲強類型對象。首先得有個基本類:
Imports System
Imports System.Data
Imports System.Data.SqlClient
Imports System.Runtime.Serialization
Namespace SqlTypes
<Serializable()> _
<System.ComponentModel.DesignerCategory("Code")> _
Public MustInherit Class SqlTableTypeBase
Inherits DataTable
Public Sub New()
MyBase.New()
Initialize()
End Sub
Public Sub New(ByVal tableName As String)
MyBase.New(tableName)
Initialize()
End Sub
Public Sub New(ByVal tableName As String, ByVal tableNamespace As String)
MyBase.New(tableName, tableNamespace)
Initialize()
End Sub
Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)
MyBase.New(info, context)
End Sub
''' <summary>
''' Implement this method to create the columns in the data table to match the SQL server user defined table type
''' </summary>
''' <remarks></remarks>
Protected MustOverride Sub Initialize()
Public Function CreateParameter(parameterName As String) As SqlParameter
Dim p As New SqlParameter(parameterName, SqlDbType.Structured)
p.Value = Me
Return p
End Function
End Class
End Namespace
創建的SQL類型的實現:
Imports System
Imports System.Data
Imports System.Runtime.Serialization
Namespace SqlTypes
<Serializable()> _
<System.ComponentModel.DesignerCategory("Code")> _
Public Class DateRange
Inherits SqlTableTypeBase
Public Sub New()
MyBase.New()
End Sub
Public Sub New(ByVal tableName As String)
MyBase.New(tableName)
End Sub
Public Sub New(ByVal tableName As String, ByVal tableNamespace As String)
MyBase.New(tableName, tableNamespace)
End Sub
Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)
MyBase.New(info, context)
End Sub
'TODO: throw some more overloaded constructors in here...
Public Sub New(startDate As DateTime?, endDate As DateTime?)
MyBase.New()
Me.StartDate = startDate
Me.EndDate = endDate
End Sub
Public Property StartDate As DateTime?
Get
Return CType(Me.Rows(0)(0), DateTime?)
End Get
Set(value As DateTime?)
Me.Rows(0)(0) = value
End Set
End Property
Public Property EndDate As DateTime?
Get
Return CType(Me.Rows(0)(1), DateTime?)
End Get
Set(value As DateTime?)
Me.Rows(0)(1) = value
End Set
End Property
Protected Overrides Sub Initialize()
Me.Columns.Add(New DataColumn("StartDate", GetType(DateTime?)))
Me.Columns.Add(New DataColumn("EndDate", GetType(DateTime?)))
Me.Rows.Add({Nothing, Nothing})
End Sub
End Class
End Namespace
和:
Imports System
Imports System.Data
Imports System.Runtime.Serialization
Namespace SqlTypes
<Serializable()> _
<System.ComponentModel.DesignerCategory("Code")> _
Public Class Paging
Inherits SqlTableTypeBase
Public Sub New()
MyBase.New()
End Sub
Public Sub New(ByVal tableName As String)
MyBase.New(tableName)
End Sub
Public Sub New(ByVal tableName As String, ByVal tableNamespace As String)
MyBase.New(tableName, tableNamespace)
End Sub
Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)
MyBase.New(info, context)
End Sub
'TODO: throw some more overloaded constructors in here...
Public Sub New(pageNumber As Integer?, pageSize As Integer?)
MyBase.New()
Me.PageNumber = pageNumber
Me.PageSize = pageSize
End Sub
Public Sub New(sortField As String, sortDirection As String)
MyBase.New()
Me.SortField = sortField
Me.SortDirection = sortDirection
End Sub
Public Sub New(pageNumber As Integer?, pageSize As Integer?, sortField As String, sortDirection As String)
Me.New(pageNumber, pageSize)
Me.SortField = sortField
Me.SortDirection = sortDirection
End Sub
Public Property PageNumber As Integer?
Get
Return CType(Me.Rows(0)(0), Integer?)
End Get
Set(value As Integer?)
Me.Rows(0)(0) = value
End Set
End Property
Public Property PageSize As Integer?
Get
Return CType(Me.Rows(0)(1), Integer?)
End Get
Set(value As Integer?)
Me.Rows(0)(1) = value
End Set
End Property
Public Property SortField As String
Get
Return CType(Me.Rows(0)(2), String)
End Get
Set(value As String)
Me.Rows(0)(2) = value
End Set
End Property
Public Property SortDirection As String
Get
Return CType(Me.Rows(0)(3), String)
End Get
Set(value As String)
Me.Rows(0)(3) = value
End Set
End Property
Protected Overrides Sub Initialize()
Me.Columns.Add(New DataColumn("PageNumber", GetType(Integer?)))
Me.Columns.Add(New DataColumn("PageSize", GetType(Integer?)))
Me.Columns.Add(New DataColumn("SortField", GetType(String)))
Me.Columns.Add(New DataColumn("SortDirection", GetType(String)))
Me.Rows.Add({Nothing, Nothing, Nothing, Nothing})
End Sub
End Class
End Namespace
實例化對象,並在構造函數中設置的值,然後簡單地從對象獲取參數,並將其附加到存儲過程命令對象的參數集合中。
cmd.Parameters.Add(New DateRange(startDate, endDate).CreateParameter("DateRangeParams"))
cmd.Parameters.Add(New Paging(pageNumber, pageSize).CreateParameter("PagingParams"))
編輯 因爲這個答案是圍繞強類型,我想我應該在方法簽名中添加強類型的例子:
'method signature with UDTs
Public Function GetMyReport(customParam1 as Integer, timeFrame as DateRange, pages as Paging) as IDataReader
'method signature without UDTs
Public Function GetMyReport(customParam1 as Integer, startDate as DateTime, endDate as DateTime, pageNumber as Integer, pageSize as Integer)
我考慮過的一個潛在解決方案是一個xml序列化的C#對象,它用UDF反序列化爲一個數據表。在每個程序中通過關鍵名稱捕捉適當的值仍然很麻煩。最後,我只是想對這個概念做更多的研究 - 是否可以在其他平臺上使用?有人開發了一個過濾層/ api來使SQL Server更容易嗎?提前致謝。 – mellodev
我使用了很多動態SQL。在這種情況下,通過傳遞WHERE子句來解決問題。 –
感謝您的輸入。我們已經做了大量的動態sql,實際上是存儲在應用程序中的這個項目的所有SQL,我們在其中附加了SqlDataParameters並根據需要執行我們自己專有的WHERE子句注入。然而,每個SQL塊都會有很多重複的參數和邏輯以滿足通常的過濾需求,所以我試圖找到一個將這些封裝成單個參數的模式。 – mellodev