没有调用Dapper TypeHandler.SetValue()

我正在测试Dapper将对象加载/持久化到Oracle数据库,并且为了管理Oracle的Guid存储,我需要一个SqlMapper.TypeHandler 。 从数据库加载Guid列时,会调用Parse方法,但是当我尝试使用Guid参数执行SQL语句时,会出现以下exception:

System.ArgumentException未处理; Message = Value不在预期范围内.Source = Oracle.DataAccess。

在调试中,我可以看到我从数据库加载我的类时调用了我的处理程序的Parse()方法,但是SetValue()mdethod却没有。

重现exception的代码如下


 CREATE TABLE foo (id RAW (16) NOT NULL PRIMARY KEY, name VARCHAR2 (30) NOT NULL); INSERT INTO foo (id, name) VALUES (SYS_GUID (), 'Bar'); COMMIT; 

 using System; using System.Linq; using Dapper; using Oracle.DataAccess.Client; namespace Program { public class Foo { public Guid Id { get; set; } public string Name { get; set; } } class GuidTypeHandler : SqlMapper.TypeHandler { public override Guid Parse(object value) { Console.WriteLine("Handling Parse of {0}", value); var inVal = (byte[])value; byte[] outVal = new byte[] { inVal[3], inVal[2], inVal[1], inVal[0], inVal[5], inVal[4], inVal[7], inVal[6], inVal[8], inVal[9], inVal[10], inVal[11], inVal[12], inVal[13], inVal[14], inVal[15] }; return new Guid(outVal); } public override void SetValue(System.Data.IDbDataParameter parameter, Guid value) { Console.WriteLine("Handling Setvalue of {0}", value); var inVal = value.ToByteArray(); byte[] outVal = new byte[] { inVal[3], inVal[2], inVal[1], inVal[0], inVal[5], inVal[4], inVal[7], inVal[6], inVal[8], inVal[9], inVal[10], inVal[11], inVal[12], inVal[13], inVal[14], inVal[15] }; parameter.Value = outVal; } } class Program { static void Main(string[] args) { SqlMapper.AddTypeHandler(new GuidTypeHandler()); var conn = new OracleConnection(Resources.ConnectionString); var def = new CommandDefinition("select id, name from foo"); conn.Open(); var foo = conn.Query(def).First(); Console.WriteLine(foo.Id + "; " + foo.Name); foo.Name = "New Bar"; def = new CommandDefinition( "UPDATE foo SET name = :name WHERE id = :id", parameters: new { ID = foo.Id, NAME = foo.Name }); var rows = conn.Execute(def); Console.WriteLine("{0} rows inserted", rows); Console.ReadLine(); } } } 

我通过编写.NET Guid类的包装器解决了这个问题。 不太理想,因为你最终得到了DTO课程中的包装,但它确实有效。

包装类:

 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; } } } 

处理程序类:

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

一个使用包装类的DTO类:

 public class FooDto { public OracleGuid Id { get; set; } public string Name { get; set; } } 

注意我使用RAW(16)将它们存储在Oracle中,而不是内置的Oracle Guids中。

编辑看起来这可能是一个错误,可能已修复: https : //github.com/StackExchange/dapper-dot-net/issues/253 。 看起来它还没有进入NuGet包,所以我还没试过。