Сопоставить строку с гидом с помощью Dapper - PullRequest
10 голосов
/ 05 мая 2011

Я использую Dapper для разработки некоторых инструментов нагрузочного тестирования, которым необходим доступ к базе данных PostgreSQL.Эта конкретная версия PostgreSQL изначально не поддерживает GUID, поэтому значения GUID хранятся в виде 32-символьных строк.Значения преобразуются в строки с использованием someGuid.ToString("N"), преобразование обратно в Guid может быть выполнено с использованием new Guid(stringValueFromColumn).

Мой вопрос: как мне заставить Dapper читать строки и преобразовывать их обратно в Guids?

Я попытался изменить отображение DbType, но это не сработало.

Ответы [ 4 ]

18 голосов
/ 07 мая 2011

Пожалуй, самый простой способ сделать это (не ожидая ответа) - это иметь второе свойство:

public Guid Foo {get;set;}

public string FooString {
    get { return Foo.ToString("N"); }
    set { Foo = new Guid(value); }
}

И в вашем запросе псевдоним столбца как FooString.

Конечно, тогда возникает вопрос: должен ли dapper поддерживать частные свойства для такого типа вещей? На что я говорю: наверное.

4 голосов
/ 13 сентября 2018

Я знаю, что это старый вопрос, но для любого, кто наткнется на эту тему, как я сделал сегодня, я опубликую свое решение.

Я использую MySql, но у него та же проблема, поскольку я сохраняю Guid в виде строки. Чтобы исправить сопоставление без псевдонима столбца, я использовал следующее:

public class MySqlGuidTypeHandler : SqlMapper.TypeHandler<Guid>
{
    public override void SetValue(IDbDataParameter parameter, Guid guid)
    {
        parameter.Value = guid.ToString();
    }

    public override Guid Parse(object value)
    {
        return new Guid((string)value);
    }
}

И в моем Startup.cs:

public void ConfigureServices(IServiceCollection services)
    {
        SqlMapper.AddTypeHandler(new MySqlGuidTypeHandler());
        SqlMapper.RemoveTypeMap(typeof(Guid));
        SqlMapper.RemoveTypeMap(typeof(Guid?));
    }
3 голосов
/ 24 июля 2015

Это старый вопрос, но я чувствую, что он нуждается в обновлении, поскольку Dapper теперь поддерживает частные свойства, на которые Марк ссылался в своем ответе.

private String UserIDString { get; set; }
public Guid UserID
{
    get
    {
        return new Guid(UserIDString);
    }
    private set
    {
        UserID = value;
    }
}

Затем в SQL присвойте столбцу идентификатора псевдоним, чтобы сопоставить его с частным свойством, а не с фактическим свойством:

SELECT UserID AS UserIDString FROM....
2 голосов
/ 06 мая 2011

Я взломал решение вместе.Насколько я могу судить, нет способа дать Dapper команду генерировать альтернативный код привязки для определенного типа, поэтому я изменил метод GetClassDeserializer, чтобы принудительно заставить тип unbox в строку, если свойство является guid.Затем я повторно использовал код, который генерирует вызов конструктора для перечислений.

Вот измененный фрагмент кода (начиная со строки 761 версии rf6d62f91f31a):

// unbox nullable enums as the primitive, i.e. byte etc
  var nullUnderlyingType = Nullable.GetUnderlyingType( item.Info.Type );
  var unboxType = nullUnderlyingType != null && nullUnderlyingType.IsEnum ? nullUnderlyingType : item.Info.Type;
  if( unboxType == typeof(Guid))
  {
    unboxType = typeof (string);
  }
  il.Emit( OpCodes.Unbox_Any, unboxType ); // stack is now [target][target][typed-value]
  if (  ( item.Info.Type == typeof( Guid ) && unboxType == typeof( string ) ) 
        || ( nullUnderlyingType != null && nullUnderlyingType.IsEnum ) )
  {
    il.Emit( OpCodes.Newobj, item.Info.Type.GetConstructor( new[] { nullUnderlyingType ?? unboxType} ) );
  }

  il.Emit( OpCodes.Callvirt, item.Info.Setter ); // stack is now [target]
...