2011-05-05 157 views
9

我正在使用Dapper来找出一些需要访问PostgreSQL数据库的负载测试工具。这个特定版本的PostgreSQL原生不支持GUID,因此GUID值存储为32个字符的字符串。这些值使用someGuid.ToString("N")转换为字符串,转换回Guid可以使用new Guid(stringValueFromColumn)完成。将字符串映射到Dapper的GUID

我的问题是如何让Dapper读取字符串并将它们转换回Guids?

我试着修改DbType映射,但不起作用。

+0

虽然你在你的问题提这个突出的是,我错过了你提到你正在使用“本机不支持GUID”的数据库。值得注意的是,在数据库中,可以将tSQL中的UNIQUEIDENTIFIER(或类似)映射到C#中的Guid([eg](https://github.com/StackExchange/dapper-dot-net/issues/447)) – dumbledad 2016-02-01 14:17:02

回答

16

或许要做到这一点(不等待短小精悍)最简单的方法是让第二个属性:

public Guid Foo {get;set;} 

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

而在您的查询中,别名为FooString

当然,这就提示了这个问题:应该为这种类型的东西支持私有属性?我可以说:可能。

+0

那么,这比在Dapper上劈手要干净一点。允许设置私有属性(或字段)会很好。 – 2011-05-09 10:19:29

+0

@Marnix - 是的,我打算加入 – 2011-05-09 10:26:30

+0

@Marnix - 现在都存在,顺便说一句(在源文件中 - 我还没有取消部署nuget包) – 2011-05-09 12:56:47

2

我一起攻击了一个解决方案。据我所知,没有办法指示Dapper为特定类型生成备用绑定代码,所以我修改了GetClassDeserializer方法以强制unbox类型为字符串,如果属性为guid。 接下来,我重新使用了为枚举生成构造函数调用的代码。

下面是修改后的代码片段(在转rf6d62f91f31a的761行开始):

// 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]
+0

类型强制是我特意避免的,你会不会介意在我们的bug跟踪器上发布一个特性请求,看看它是否合适,请记住,如果postgres中的guid恰好为31个字符长度,将会出现壮观的爆炸。 .. – 2011-05-07 11:14:27

+0

@Sam - meh,GIGO;亲自这会不会很困扰我。在此之前,L2S在这里进行了一些*转换(包括通过名称作为字符串的枚举)。 – 2011-05-07 11:43:20

+0

@Sam谢谢,我发布了功能请求。 – 2011-05-09 10:51:15

3

这是一个古老的问题,但我觉得它需要更新,因为Dapper现在支持私有属性,Marc在他的回答中引用了它。

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

然后在SQL给你的ID列的别名将其映射到私有财产,而不是实际的属性:

SELECT UserID AS UserIDString FROM....