Более скучный ряд в JSON - PullRequest
       23

Более скучный ряд в JSON

3 голосов
/ 10 апреля 2019

Вопрос

У нас есть Dapper Row в результате Dapper Query, который я хочу сохранить как строку json в нашей базе данных.К сожалению, я не могу заставить это работать.Итак, давайте начнем с некоторой справочной информации.

Справочная информация

Мы выполняем проект, в котором мы извлекаем Имена таблиц из таблицы,знать, к каким таблицам мы должны обратиться.Мы также хотим, чтобы это было как можно более гибким, поэтому мы решили не использовать конкретный POCO для наших данных.

Мы используем SQL Server 2014, поэтому, к сожалению, у нас нет опции 'FOR JSON'Пока.

Код

Наш код выглядит примерно так, где GetData - это наш фактический запрос:

var data = _queryHandler.Handle( new GetData(tableName.ToString(), 0), database));

Технически дескриптор просто подключается к базе данных, вызывая

conn.QueryAsync(query, parameters)

GetData выглядит следующим образом (упрощенно):

EXEC ('SELECT * FROM ' + @table + ')'

Reasoning

Поскольку имя таблицы каждый раз отличается, мы не хотим принудительно устанавливать 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, я застреваю в destinationType, так как не хочу определенного типа - ну, за исключением объекта 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);
    }
}

Единственное, что приходит мне в голову, - это извлечь каждый столбец и построить из него объект типа, но, как я уже сказал, мы не хотим использовать модель / тип дляданные, как мы хотим, чтобы это было гибким.

Может ли кто-нибудь указать мне правильное направление?У меня такое чувство, будто я упускаю что-то простое.

1 Ответ

3 голосов
/ 10 апреля 2019

Если вы используете нетипизированный 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
...