Dapper TypeHandler.SetValue() not being called

前端 未结 2 1599
时光取名叫无心
时光取名叫无心 2020-12-16 02:08

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

相关标签:
2条回答
  • 2020-12-16 02:32

    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.

    0 讨论(0)
  • 2020-12-16 02:33

    In case anyone else stumbles upon this post with a similar problem, I found a solution to handling Guids 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();
        }
    }
    
    0 讨论(0)
提交回复
热议问题