I am testing Dapper to load / persist objects to an Oracle database, and to manage Oracle\'s Guid storage I need a SqlMapper.TypeHandler
. When loadi
I worked around this issue by writing a wrapper around the .NET Guid class. Not ideal since you end up with the wrapper in your DTO classes but it works.
The wrapper class:
public class OracleGuid
{
private Guid dotNetGuid;
public OracleGuid(Guid guid)
{
this.dotNetGuid = guid;
}
public OracleGuid(Byte[] byteArray)
{
this.dotNetGuid = new Guid(byteArray);
}
public Guid InternalGuid { get { return dotNetGuid; } }
}
The handler class:
public class OracleGuidHandler : SqlMapper.TypeHandler<OracleGuid>
{
public override OracleGuid Parse(object value)
{
return new OracleGuid((byte[]) value);
}
public override void SetValue(System.Data.IDbDataParameter parameter, OracleGuid value)
{
parameter.Value = value.InternalGuid.ToByteArray();
}
}
A DTO class that makes use of the wrapper class:
public class FooDto
{
public OracleGuid Id { get; set; }
public string Name { get; set; }
}
Note I'm using RAW(16) to store these in Oracle, not the built in Oracle Guids.
EDIT Looks like this may have been a bug and may have been fixed: https://github.com/StackExchange/dapper-dot-net/issues/253. Doesn't look like it has made it into the NuGet package yet so I haven't tried it out yet.
In case anyone else stumbles upon this post with a similar problem, I found a solution to handling Guid
s without the need for wrappers.
The problem in Dapper is the order in which Dapper searches for matching DbType
and TypeHandler
implementations. Dapper prefers "native" DbType
for a Guid
(in SqlMapper#LookupDbType
). In order to make Dapper use your own implementation, you have to remove the default mapping in addition to adding your own TypeHandler
:
SqlMapper.AddTypeHandler<Guid>(new GuidTypeHandler());
SqlMapper.RemoveTypeMap(typeof(Guid));
SqlMapper.RemoveTypeMap(typeof(Guid?));
I currently use a string
-based implementation when working with SQLite:
public class GuidAsStringHandler : SqlMapper.TypeHandler<Guid>
{
public override Guid Parse(object value)
{
return new Guid((string) value);
}
public override void SetValue(IDbDataParameter parameter, Guid value)
{
parameter.Value = value.ToString();
}
}