Вопрос
У нас есть Dapper Row в результате запроса Dapper, который я хочу сохранить в виде строки json в нашей базе данных. К сожалению, я не могу заставить это работать. Итак, давайте начнем с некоторой справочной информации.
Справочная информация
Мы делаем проект, в котором мы извлекаем Имена таблиц из таблицы, чтобы знать, к каким таблицам мы должны обращаться. Мы также хотим, чтобы это было как можно более гибким, поэтому мы решили не использовать конкретный POCO для наших данных.
Мы используем SQL Server 2014, поэтому, к сожалению, у нас пока нет опции «ДЛЯ JSON».
Код
Наш код выглядит примерно так, где GetData — это наш фактический запрос:
var data = _queryHandler.Handle(new GetData(tableName.ToString(), 0), database);
Технически дескриптор просто подключается к базе данных, вызывая
conn.QueryAsync(query, parameters)
GetData выглядит так (упрощенно):
EXEC ('SELECT * FROM ' + @table + ')'
Рассуждение
Поскольку имя таблицы каждый раз меняется, мы не хотим навязывать вывод POCO. Иногда это пользователь, иногда роль, так сказать, поэтому невозможно предугадать, какой результат он вернет.
Результаты
Это прекрасно работает. Мы можем извлечь данные из нашей переменной, и это выглядит как IEnumerable, что должно быть в порядке. Я так понимаю, мы можем просто читать их в цикле и извлекать строки. Пока нет проблем.
Проблема под рукой
Следующее, что мы хотим сделать, это преобразовать данные из указанного DapperRow в строку json, но я не могу заставить данные вести себя как строку json, поскольку JsonConvert.SerializeObject с треском терпит неудачу. DapperRow выглядит так (опять же, упрощенно).
{{DapperRow, Id = '07501399-b385-4d8e-bacc-gad9d04c35f7', UserName = 'test8', ApplicationId = '4721fafb-12e6-4e3c-9298-etd82d18a0cb', IsApproved = 'True', IsLockedOut = 'False', CreateDate = '26-3-2019 07:52:55' }}
Я уже изучил такие вещи, как SqlMapper.ITypeHandler
, но до сих пор не дошел. Например, с TypeHandler я застреваю на целевом типе, поскольку мне не нужен конкретный тип — ну, кроме объекта json. Но это не принятый тип.
public class JsonObjectTypeHandler : SqlMapper.ITypeHandler
{
public void SetValue(IDbDataParameter parameter, object value)
{
parameter.Value = (value == null)
? (object)DBNull.Value
: JsonConvert.SerializeObject(value);
parameter.DbType = DbType.String;
}
public object Parse(Type destinationType, object value)
{
return JsonConvert.DeserializeObject(value.ToString(), destinationType);
}
}
Единственная другая вещь, которая приходит мне в голову, - это извлечь каждый столбец и построить из него объект типа, но, как я уже сказал, мы не хотим использовать модель/тип для данных, поскольку мы хотим, чтобы они были гибкими. .
Может ли кто-нибудь указать мне в правильном направлении? У меня такое чувство, что я упускаю из виду что-то простое.
Если вы используете нетипизированный Query
API, каждая возвращаемая строка также является IDictionary<string,object>
(в дополнение к dynamic
API), которая обычно отлично работает с JsonConvert
; например, следующее работает нормально для меня:
var tables = (from row in await conn.QueryAsync("select top 5 * from sys.tables")
select (IDictionary<string, object>)row).AsList();
var json = JsonConvert.SerializeObject(tables, Formatting.Indented);
System.Console.WriteLine(json);
вывод:
[
{
"name": "spt_fallback_db",
"object_id": 117575457,
"principal_id": null,
"schema_id": 1,
"parent_object_id": 0,
"type": "U ",
"type_desc": "USER_TABLE",
"create_date": "2003-04-08T09:18:01.557",
"modify_date": "2017-08-22T19:40:40.763",
"is_ms_shipped": true,
"is_published": false,
"is_schema_published": false,
"lob_data_space_id": 0,
"filestream_data_space_id": null,
"max_column_id_used": 8,
... etc
Вывод вашего запроса был точно таким же, как мой вывод, так что проблема не в этом. По-видимому, единственное изменение, которое мне пришлось сделать, это добавить АсСписок() в запрос, чтобы он работал правильно. Так что я был прав в том, что это было что-то простое — спасибо, что помогли мне разобраться!
Вы не можете использовать
JsonConvert.SerializeObject(result)
?