我正在使用Dapper来找出一些需要访问PostgreSQL数据库的负载测试工具。这个特定版本的PostgreSQL原生不支持GUID,因此GUID值存储为32个字符的字符串。这些值使用someGuid.ToString("N")
转换为字符串,转换回Guid可以使用new Guid(stringValueFromColumn)
完成。将字符串映射到Dapper的GUID
我的问题是如何让Dapper读取字符串并将它们转换回Guids?
我试着修改DbType映射,但不起作用。
我正在使用Dapper来找出一些需要访问PostgreSQL数据库的负载测试工具。这个特定版本的PostgreSQL原生不支持GUID,因此GUID值存储为32个字符的字符串。这些值使用someGuid.ToString("N")
转换为字符串,转换回Guid可以使用new Guid(stringValueFromColumn)
完成。将字符串映射到Dapper的GUID
我的问题是如何让Dapper读取字符串并将它们转换回Guids?
我试着修改DbType映射,但不起作用。
或许要做到这一点(不等待短小精悍)最简单的方法是让第二个属性:
public Guid Foo {get;set;}
public string FooString {
get { return Foo.ToString("N"); }
set { Foo = new Guid(value); }
}
而在您的查询中,别名为FooString
。
当然,这就提示了这个问题:应该为这种类型的东西支持私有属性?我可以说:可能。
那么,这比在Dapper上劈手要干净一点。允许设置私有属性(或字段)会很好。 – 2011-05-09 10:19:29
@Marnix - 是的,我打算加入 – 2011-05-09 10:26:30
@Marnix - 现在都存在,顺便说一句(在源文件中 - 我还没有取消部署nuget包) – 2011-05-09 12:56:47
我一起攻击了一个解决方案。据我所知,没有办法指示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]
类型强制是我特意避免的,你会不会介意在我们的bug跟踪器上发布一个特性请求,看看它是否合适,请记住,如果postgres中的guid恰好为31个字符长度,将会出现壮观的爆炸。 .. – 2011-05-07 11:14:27
@Sam - meh,GIGO;亲自这会不会很困扰我。在此之前,L2S在这里进行了一些*转换(包括通过名称作为字符串的枚举)。 – 2011-05-07 11:43:20
@Sam谢谢,我发布了功能请求。 – 2011-05-09 10:51:15
这是一个古老的问题,但我觉得它需要更新,因为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....
虽然你在你的问题提这个突出的是,我错过了你提到你正在使用“本机不支持GUID”的数据库。值得注意的是,在数据库中,可以将tSQL中的UNIQUEIDENTIFIER(或类似)映射到C#中的Guid([eg](https://github.com/StackExchange/dapper-dot-net/issues/447)) – dumbledad 2016-02-01 14:17:02