使用Dapper将字符串映射到guid

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

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

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

也许最简单的方法(没有等待精致)是有第二个属性:

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

在查询中,将列别名为FooString

当然,这会引发一个问题:应该为这种类型的东西支持私有属性吗? 我说的话:可能。

这是一个老问题,但我觉得它需要更新,因为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.... 

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

这是修改后的代码片段(从rev.rf6d62f91f31a第761行开始):

 // unbox nullable enums as the primitive, ie 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] 

我知道这是一个古老的问题,但对于任何一个绊到这个线程的人,就像我今天所做的那样,我会发布我的解决方案。

我正在使用MySql,但它存在同样的问题,因为我将Guid存储为字符串。 要修复映射而不必对列进行别名,我使用了以下内容:

 public class MySqlGuidTypeHandler : SqlMapper.TypeHandler { 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?)); }