Pergunta

Estou usando o Dapper para desenvolver algumas ferramentas de teste de carga que precisam acessar um banco de dados PostgreSQL.Esta versão particular do PostgreSQL não suporta GUIDs nativamente, então os valores GUID são armazenados como strings de 32 caracteres.Os valores são convertidos em strings usando someGuid.ToString("N"), a conversão de volta para Guid pode ser feita usando new Guid(stringValueFromColumn).

Minha pergunta é como faço o Dapper ler as strings e convertê-las de volta em Guids?

Tentei modificar o mapeamento DbType, mas não funcionou.

Foi útil?

Solução

Talvez a maneira mais simples de fazer isso (sem esperar por dapper) seja ter uma segunda propriedade:

public Guid Foo {get;set;}

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

E na sua consulta, coloque o alias da coluna como FooString.

Claro, isso levanta a questão: o dapper deve oferecer suporte a propriedades privadas para esse tipo de coisa?Ao que eu digo: provavelmente.

Outras dicas

Sei que essa é uma pergunta antiga, mas para qualquer um que encontrar esse tópico como fiz hoje, postarei minha solução.

Estou usando o MySql, mas está com o mesmo problema já que armazeno o Guid como uma string. Para corrigir o mapeamento sem ter que usar o alias da coluna, usei o seguinte:

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);
    }
}

E em meu Startup.cs:

public void ConfigureServices(IServiceCollection services)
    {
        SqlMapper.AddTypeHandler(new MySqlGuidTypeHandler());
        SqlMapper.RemoveTypeMap(typeof(Guid));
        SqlMapper.RemoveTypeMap(typeof(Guid?));
    }

Esta é uma pergunta antiga, mas sinto que precisa ser atualizada, pois o Dapper agora oferece suporte a propriedades privadas, às quais Marc se referiu em sua resposta.

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

Então, em SQL, dê à sua coluna de ID um alias para mapeá-la para a propriedade privada e não para a propriedade real:

SELECT UserID AS UserIDString FROM....

Eu hackeei uma solução juntos.Até onde eu posso dizer, não há como instruir o Dapper a gerar um código de ligação alternativo para um tipo específico, então modifiquei o método GetClassDeserializer para forçar o tipo unbox a string se a propriedade for um guid. Em seguida, reutilizei o código que gera uma chamada de construtor para enums.

Aqui está o snippet de código modificado (começando na linha 761 da rev. 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]
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top