[英]How are parameters passed from SQL Server to a CLR based stored procedure?
[英]How can I retrieve a list of parameters from a stored procedure in SQL Server
使用C#和System.Data.SqlClient,有沒有辦法在實際執行之前檢索屬於SQL Server上的存儲過程的參數列表?
我有一個“多環境”場景,其中有相同數據庫架構的多個版本。 環境的示例可以是“開發”,“分段”和“生產”。 “開發”將有一個版本的存儲過程,“Staging”將有另一個版本。
我想要做的就是在傳遞一個值並調用存儲過程之前驗證參數是否存在。 避免SqlException而不是必須捕獲它對我來說是一個加分。
約書亞
您需要SqlCommandBuilder.DeriveParameters(SqlCommand)方法。 請注意,它需要額外的數據庫往返,因此它的性能有點顯着。 您應該考慮緩存結果。
一個示例電話:
using (SqlConnection conn = new SqlConnection(CONNSTRING))
using (SqlCommand cmd = new SqlCommand("StoredProc", conn)) {
cmd.CommandType = CommandType.StoredProcedure;
SqlCommandBuilder.DeriveParameters(cmd);
cmd.Parameters["param1"].Value = "12345";
// ....
}
您可以使用SqlCommandBuilder.DeriveParameters()(請參閱SqlCommandBuilder.DeriveParameters - 獲取存儲過程的參數信息 - ADO.NET教程 )或者這種方式不是那么優雅。
雖然它不完全是您想要的,但這里有一些示例代碼,它使用SqlConnection.GetSchema()方法返回與數據庫關聯的所有存儲過程,然后返回每個存儲過程的所有參數名稱和類型。 下面的示例只是將其加載到變量中。 請注意,這也會返回所有“系統”存儲過程,這可能是不可取的。
史蒂夫
public void LoadProcedureInfo()
{
SqlConnection connection = new SqlConnection();
ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings["ConnectionString"];
connection.ConnectionString = settings.ConnectionString;
connection.Open();
DataTable procedureDataTable = connection.GetSchema("Procedures");
DataColumn procedureDataColumn = procedureDataTable.Columns["ROUTINE_NAME"];
if (procedureDataColumn != null)
{
foreach (DataRow row in procedureDataTable.Rows)
{
String procedureName = row[procedureDataColumn].ToString();
DataTable parmsDataTable = connection.GetSchema("ProcedureParameters", new string[] { null, null, procedureName });
DataColumn parmNameDataColumn = parmsDataTable.Columns["PARAMETER_NAME"];
DataColumn parmTypeDataColumn = parmsDataTable.Columns["DATA_TYPE"];
foreach (DataRow parmRow in parmsDataTable.Rows)
{
string parmName = parmRow[parmNameDataColumn].ToString();
string parmType = parmRow[parmTypeDataColumn].ToString();
}
}
}
}
SqlCommandBuilder.DeriveParameters(command)
這句話做了我需要的。
以下是我解決此問題的完整代碼示例。
Public Sub GetLogEntriesForApplication(ByVal settings As FilterSettings,
Optional ByVal RowGovernor As Integer = -1)
Dim command As New SqlCommand("GetApplicationActions",
New SqlConnection(m_environment.LoggingDatabaseConnectionString))
Dim adapter As New SqlDataAdapter(command)
Using command.Connection
With command
.Connection.Open()
.CommandType = CommandType.StoredProcedure
SqlCommandBuilder.DeriveParameters(command)
With .Parameters
If settings.FilterOnLoggingLevel Then
If .Contains("@loggingLevel") Then
.Item("@loggingLevel").Value = settings.LoggingLevel
End If
End If
If settings.FilterOnApplicationID Then
If .Contains("@applicationID") Then
.Item("@applicationID").Value = settings.ApplicationID
End If
End If
If settings.FilterOnCreatedDate Then
If .Contains("@startDate") Then
.Item("@startDate").Value = settings.CreatedDate.Ticks
End If
End If
If settings.FilterOnEndDate Then
If .Contains("@endDate") Then
.Item("@endDate").Value = settings.EndDate.Ticks
End If
End If
If settings.FilterOnSuccess Then
If .Contains("@success") Then
.Item("@success").Value = settings.Success
End If
End If
If settings.FilterOnProcess Then
If settings.Process > -1 Then
If .Contains("@process") Then
.Item("@process").Value = settings.Process
End If
End If
End If
If RowGovernor > -1 Then
If .Contains("@topRows") Then
.Item("@topRows").Value = RowGovernor
End If
End If
End With
End With
adapter.TableMappings.Clear()
adapter.TableMappings.Add("Table", "ApplicationActions")
adapter.TableMappings.Add("Table1", "Milestones")
LogEntries.Clear()
Milestones.Clear()
adapter.Fill(m_logEntryData)
End Using
End Sub
您可以使用SqlCommandBuilder對象,並調用DeriveParameters方法。
基本上你需要傳遞一個命令,設置為調用你的存儲過程,它將命中數據庫以發現參數,並在SqlCommand的Parameters屬性中創建適當的參數
編輯:你太快了!!
Mark擁有DeriveParameters的最佳實現。 正如他所說,請確保像本教程中一樣緩存。
但是,我認為這是解決數據庫sproc版本化原始問題的危險方法。 如果要通過添加或刪除參數來更改過程的簽名,則應執行以下操作之一:
依靠DeriveParameters來驗證你正在使用的sproc的哪個版本似乎是錯誤的工具,恕我直言。
幾年以來,我一直在使用帶有.NET 1.1和2.0的DeriveParameters,每次都像魅力一樣。
現在我正在使用.NET 3.5進行我的第一次任務,並且發現並且令人驚訝:DeriveParameters使用SqlDbType“Variant”創建所有參數,而不是正確的SqlDbTypes。 這在嘗試使用數字參數執行SP時會創建SqlException,因為SQL Server 2005說sql-variant類型不能被隱式轉換為int(或smallint或numeric)值。
我剛剛使用.NET CF 2.0和SQL Server 2000測試了相同的代碼,並按預期工作,為每個參數分配正確的SqlDbType。
我已經針對SQL Server 2005數據庫測試了.NET 2.0應用程序,因此不是與SQL Server相關的問題,所以它必須與.NET 3.5相關
有任何想法嗎?
所有這些ADO.NET解決方案都要求代碼庫代表您查詢數據庫的元數據。 如果你打算在任何時候取得性能打擊,也許你應該只編寫一些調用的輔助函數
Select count(*) from information_schema.parameters
where ...(proc name =.. param name=...) (pseudo-code)
或者甚至可以根據您返回的參數列表生成參數。 此技術適用於多個版本的MS SQL,有時還適用於其他ANSI SQL數據庫。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.