У меня есть сценарий, в котором я передаю имя таблицы в качестве параметра хранимой процедуре SQL Server, и она возвращает данные из этой таблицы.
Структура данных, возвращаемая хранимой процедурой, зависит от параметра (имени таблицы), который я ей передаю.
В моей существующей реализации, где структура данных фиксирована, т. е. столбцы, возвращаемые хранимой процедурой, не изменяются, мы используем предопределенные DTO, которые выглядят следующим образом:
public IList<UserDetailsDTO> GetUserDetails(int userId)
{
Dictionary<string, object> params = new Dictionary<string, object>();
params.Add("@UserId",userId);
return ExecuteProcedure<UserDetailsDTO>("spGetUserDetails", params);
}
Теперь, учитывая мое новое требование, согласно которому структура данных, возвращаемая хранимой процедурой, варьируется в зависимости от передаваемого ей параметра имени таблицы, я не уверен, как я могу сделать мои DTO динамическими.
Есть какие-нибудь отзывы или предложения по этому поводу?
«я передаю имя таблицы в качестве параметра хранимой процедуре SQL Server, и эта хранимая процедура возвращает данные из этой таблицы» такая настройка часто является признаком проблемы XY.
@GustavoOliveira В настоящее время приложение настроено с использованием ADO.NET.
Реляционные базы данных не предназначены/не предназначены для общего/DRY-кода. Они предназначены для конкретного статического кода.
Как ваше приложение будет использовать полученные значения? Если у вас есть разные места в коде, в которые передаются разные жестко запрограммированные параметры таблицы, и вы знаете, какой тип значения следует ожидать, вы можете использовать универсальный тип в своем вспомогательном методе. Если вызывающий код просто передает значения куда-то еще (например, для сериализации), вы можете просто использовать словарь.
@StriplingWarrior Имя таблицы будет передано из внешнего интерфейса на основе выбора раскрывающегося списка. Как только уровень доступа к данным вернет значения, эти значения будут возвращены на бизнес-уровень и с бизнес-уровня на контроллер API и метод действия контроллера API. вернет форму массива JSON, который будет использоваться в FE и отобразит набор результатов в сетке.
Зачем вам вообще нужны DTO? Похоже, вы просто хотите получить JSON прямо сейчас.
Вы делаете это точно так же, с фиксированным DTO для каждого вызова базы данных, даже если у вас есть одна хранимая процедура, которая возвращает разные наборы результатов (что является раздражающим и бесполезным шаблоном). например
public IList<UserDetailsDTO> GetUserDetails(int userId)
{
Dictionary<string, object> params = new Dictionary<string, object>();
params.Add("@Id",userId);
params.Add("@EntityName","UserDetails");
return ExecuteProcedure<UserDetailsDTO>("usp_GetWhatever", params);
}
«Это раздражающая и бесполезная закономерность» ✅
Нужно ли мне иметь несколько методов в DAL с фиксированным DTO для каждого параметра?
Вам следует. Но если вместо этого вы используете отражение, ваш компьютер не загорится. А если у вас нет типов DTO, вам придется сгенерировать JSON в коде. Опять же, то, что вы могли бы сделать, но я бы не стал.
Я читаю здесь между строк и предполагаю, что, возможно, схема базы данных на самом деле не связана с доменом приложения, и в этом случае было бы нецелесообразно менять код для добавления DTO каждый раз при изменении таблицы.
Я бы рекомендовал прочитать возвращенные строки в нечто вроде Dictionary<string, object>
, как описано здесь.
List<Dictionary<string, object>> items = new List<Dictionary<string, object>>();
using (var reader = await command.ExecuteReaderAsync())
{
if (reader.HasRows)
{
while (await reader.ReadAsync())
{
Dictionary<string, object> obj = new Dictionary<string, object>();
for (int i = 0; i < reader.FieldCount; i++)
{
string columnName = reader.GetName(i);
object columnValue = reader.GetValue(i);
obj[columnName] = columnValue;
}
items.Add(obj);
}
}
}
Затем просто попросите вашу функцию вернуть этот список для сериализации.
Можете ли вы использовать Microsoft Entity Framework? для .net Framework Learn.microsoft.com/en-us/aspnet/mvc/overview/getting-started/… для .net core Learn.microsoft.com/en-us/ef/core/ get-started/overview/… вот пример с StoredProcedure: stackoverflow.com/questions/29012920/…