#c# #asp.net #sql-server
Вопрос:
У меня есть один метод в моем вспомогательном классе SQL, а также перегрузка для принятия параметра:
public static DataTable GetData(string cmd_text)
{
DataTable dt = new DataTable();
SqlConnection conn = GetSqlConnection();
SqlCommand cmd = new SqlCommand
{
CommandText = cmd_text,
CommandType = CommandType.StoredProcedure,
Connection = conn
};
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
da.Fill(dt);
}
return dt;
}
Перегрузка:
public static DataTable GetData(string cmd_text, string p1)
{
DataTable dt = new DataTable();
SqlConnection conn = GetSqlConnection();
SqlCommand cmd = new SqlCommand
{
CommandText = cmd_text,
CommandType = CommandType.StoredProcedure,
Connection = conn
};
//add parameter here somehow?
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
da.Fill(dt);
}
return dt;
}
Однако на полпути мне пришло в голову, что мне нужно передать то же имя параметра, которое ожидает хранимая процедура. Я всегда мог бы обойти это, указав в своем методе другой аргумент для имени параметра или даже настроив параметры в SQL Server так, чтобы они были одинаковыми для всех моих хранимых процедур, но мне было интересно, можно ли это сделать по-другому, либо на C#, либо на SQL.
Моя теория о том, как это можно сделать, заключалась в создании хранимой процедуры-оболочки, которая могла бы вызывать другие хранимые процедуры, но я не совсем уверен, как это можно было бы реализовать, если бы это было возможно.
Комментарии:
1. и у вас всегда есть только один параметр типа string? никогда другие типы данных никогда не имеют более одного параметра?
2. Откуда берутся параметры? Если SP «ищет» параметры, вы должны установить их с
cmd.Parameters.Add(...)
помощью .3. @gsharp на данный момент, да. SQL будет неявно преобразовывать практически все, с чем я столкнусь, и все, что я могу перегрузить, но я не ожидаю, что это пройдет мимо всего проекта.
4. Используйте a
IDictionary<string,object> p
, где ключом является имя параметра, а объектом-значение.5. @Макс, ты чертов гений, пожалуйста, представь это в качестве ответа.
Ответ №1:
Шаг 0: прекратите использование DataTable
Шаг 1: используйте Dapper
Нет никакого шага 2.
Просто:
string bar = "ABC"; // just to show usage
var data = connection.Query<YourPoco>(
"SomeSpName",
new { foo = 12, bar }, // named args
commandType: CommandType.StoredProcedure).AsList();
Комментарии:
1. @Austin это отлично работает с хранимыми процедурами, как показано в примере, так что: если вы предпочитаете этот маршрут, это все равно нормально
2. Тогда проблема определенно в том, что я ничего не знаю о Щеголе, ха-ха! Мне определенно придется вернуться к этому в будущем, чтобы я мог лучше понять это.
Ответ №2:
Используйте a IDictionary<string,object> p
, где ключом является имя параметра, а объектом-значение.
public static DataTable GetData(string cmd_text, IDictionary<string, object> p1)
{
DataTable dt = new DataTable();
SqlConnection conn = GetSqlConnection();
SqlCommand cmd = new SqlCommand
{
CommandText = cmd_text,
CommandType = CommandType.StoredProcedure,
Connection = conn
};
foreach (var p in p1)
{
//add parameter here
}
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
da.Fill(dt);
}
return dt;
}
Ответ №3:
И идеи, что вы могли бы сделать:
- при запуске программы запросите все sp и все параметры, принадлежащие sp
- спрячь их где-нибудь
- перед вызовом sp извлеките параметр из кэша и адаптируйте свою команду SqlCommand
Вот запрос, чтобы получить вашу информацию из базы данных
SELECT
SCHEMA_NAME(SCHEMA_ID) AS [Schema]
,SO.name AS [ObjectName]
,SO.Type_Desc AS [ObjectType]
,P.parameter_id AS [ParameterID]
,P.name AS [ParameterName]
,TYPE_NAME(P.user_type_id) AS [ParameterDataType]
,P.max_length AS [ParameterMaxBytes]
,P.is_output AS [IsOutPutParameter]
FROM sys.objects AS SO
INNER JOIN sys.parameters AS P ON SO.OBJECT_ID = P.OBJECT_ID
ORDER BY [Schema], SO.name, P.parameter_id
(Однако я не думаю, что это поможет вам далеко продвинуться, в какой-то момент вам понадобится более одного параметра, другие типы данных и другие причудливые вещи.
Я бы использовал EF или, как предложил Марк Дэппер. Эпоха семьи и друзей закончилась.)
Комментарии:
1. Это кажется замечательной идеей, и, честно говоря, я рассматриваю ее в сравнении с идеей Макса, однако на данный момент идея Макса кажется намного проще в реализации. Я думаю, что буду держать это в заднем кармане, хотя, очень признателен!
2. @Остин, посмотри ответ Марка. Я думаю, что это лучший вариант из всех.