Как указал Роквелл, проблема здесь была связана с расположением сценариев. Переместите их в заголовок, чтобы они загружались до того, как зависимые скрипты устранили проблему.
Можно использовать SqlCommandBuilder. DeriveParameters () (см. SqlCommandBuilder. DeriveParameters - Получают информацию Параметра для Хранимой процедуры - Учебные руководства ADO.NET ) или существует этот путь , который не так изящен.
Вы хотите 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";
// ....
}
Хотя не точно, что Вы хотите, вот некоторый пример кода, который использует SqlConnection. GetSchema () метод для возврата всех хранимых процедур, связанных с базой данных, и затем впоследствии всех названий параметра и типов для каждой хранимой процедуры. Пример ниже просто загружает это в переменные. Обратите внимание, что это также возвращает все "системные" хранимые процедуры, которые не могли бы быть желательными.
Steve
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.
В основном необходимо передать его команда, которая является установкой для вызова сохраненного proc, и это поразит DB, чтобы обнаружить параметры и создать соответствующие параметры в свойстве Parameters РЕДАКТИРОВАНИЯ SqlCommand
: Вы слишком быстры!!
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
Все эти решения ADO.NET, просит библиотека кода запрашивать метаданные базы данных от Вашего имени. Если Вы собираетесь получить тот удар производительности во всяком случае, возможно, необходимо просто записать некоторым функциям помощника тот вызов
Select count(*) from information_schema.parameters
where ...(proc name =.. param name=...) (pseudo-code)
Или, возможно, даже генерируйте свои параметры на основе списка параметрического усилителя, который Вы возвращаете. Эта техника будет работать с несколькими версиями MS SQL и иногда другие базы данных ANSI SQL.
У Mark есть лучшая реализация DeriveParameters. Как он сказал, удостоверьтесь Вы кэш как в это учебное руководство .
Однако, я думаю, что это - опасный способ решить Вашу исходную проблему базы данных sproc управление версиями. Если Вы собираетесь изменить подпись процедуры путем добавления или удаления параметров, необходимо выполнить одно из следующих действий:
Доверие DeriveParameters для проверки, какую версию sproc Вы используете, походит на неправильный инструмент для задания, по моему скромному мнению.
I have been using DeriveParameters with .NET 1.1 and 2.0 since a couple of years now, and worked like a charm every time.
Now I'm working on my first assignment with .NET 3.5, and just found and ugly surprise: DeriveParameters is creating all parameters with SqlDbType "Variant", instead proper SqlDbTypes. This is creating a SqlException when trying to execute SPs with numeric parameters, because SQL Server 2005 says that sql-variant types cant be implictily converted to int (or smallint, or numeric) values.
I just tested the same code with .NET CF 2.0 and SQL Server 2000, and worked as expected, assigning the correct SqlDbType to each parameters.
I had tested .NET 2.0 apps against SQL Server 2005 Databases, so is not a SQL Server related issue, so it has to be something related with .NET 3.5
Any ideas?