Сохранение словаря как JSON в SQL с помощью Dapper

#c# #json #dictionary #dapper

#c# #json #словарь #dapper

Вопрос:

Мне нужно сохранить словарь в моей таблице с помощью Dapper. Я почерпнул из других сообщений, что мне нужно использовать материал SqlMapper, который теперь доступен в Dapper.

В моем примере здесь у меня есть свойство с именем ExtendedProperties, которое я хочу сериализовать в JSON и поместить в столбец ExtendedProperties моей таблицы. Вот код, который я использую, чтобы попытаться это сделать. Обратите внимание, что этот код работает для гидратации при выходе, но завершается ошибкой при вставке с ошибкой:

Не существует сопоставления из системы типов объектов.Коллекции.Generic.KeyValuePair`2[[System.Строка, mscorlib, версия = 4.0.0.0, Культура = нейтральная, PublicKeyToken=b77a5c561934e089],[System.Объект, mscorlib, версия = 4.0.0.0, Культура = нейтральная, PublicKeyToken=b77a5c561934e089]] к известному собственному типу управляемого поставщика.’.

 public class ExtendableObject
{
    public ExtendableObject()
    {
        ExtendedProperties = new Dictionary<string, object>();
    }

    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public Dictionary<string, object> ExtendedProperties { get; set; }

    private string ExtendedPropertiesJson
    {
        get
        {
            return JsonConvert.SerializeObject(ExtendedProperties);
        }
        set
        {
            ExtendedProperties = JsonConvert.DeserializeObject<Dictionary<string, object>>(value);
        }
    }
}

public class ExtendableObjectTypeMap : SqlMapper.ITypeMap
{
    private readonly SqlMapper.ITypeMap _original;

    public ExtendableObjectTypeMap(SqlMapper.ITypeMap original)
    {
        _original = original;
    }

    public ConstructorInfo FindConstructor(string[] names, Type[] types)
    {
        return _original.FindConstructor(names, types);
    }

    public SqlMapper.IMemberMap GetConstructorParameter(System.Reflection.ConstructorInfo constructor, string columnName)
    {
        return _original.GetConstructorParameter(constructor, columnName);
    }

    public SqlMapper.IMemberMap GetMember(string columnName)
    {
        if (columnName == "ExtendedProperties")
        {
            return new ExtendedPropertiesMemberMap();
        }
        else
        {
            return _original.GetMember(columnName);
        }
    }

    /// <summary>
    /// A mapper that finds a private member to do the serialization and hydration
    /// </summary>
    public class ExtendedPropertiesMemberMap : SqlMapper.IMemberMap
    {
        public string ColumnName
        {
            get { return "ExtendedProperties"; }
        }

        public FieldInfo Field
        {
            get { return typeof(ExtendableObject).GetMember("ExtendedPropertiesJson", BindingFlags.Instance | BindingFlags.NonPublic).Single() as FieldInfo; }
        }

        public Type MemberType
        {
            get { return typeof(string); }
        }

        public ParameterInfo Parameter
        {
            get 
            { 
                return null; 
            }
        }

        public PropertyInfo Property
        {
            get { return typeof(ExtendableObject).GetMember("ExtendedPropertiesJson", BindingFlags.Instance | BindingFlags.NonPublic).Single() as PropertyInfo; }
        }
    }

SqlMapper.SetTypeMap(typeof(ExtendableObject), new ExtendableObjectTypeMap(SqlMapper.GetTypeMap(typeof(ExtendableObject))));
  

Комментарии:

1. Могу ли я уточнить: вы намерены хранить json в виде строки? Или для сопоставления пар ключ / значение с параметрами? Или?

2. Я сохраняю весь словарь <строка, объект> в виде строки в столбце nvarchar (max) в формате JSON. Это устаревший код, который я конвертирую из NHibernate, который использует пользовательский тип для выполнения этого в настоящее время.

3. В качестве действительно быстрого грязного решения я иногда использую другое свойство для хранения строкового значения значения столбца таблицы, из которого записывается / считывается база данных. Это свойство преобразует список / словарь в методе get в строку, а в наборе обновляет список / словарь всякий раз, когда задается строковое значение.

4. У меня было такое же исключение. Отладка показала, что я на самом деле передавал динамику.