2014-08-29 26 views
8

我正在測試Dapper以將對象加載/保存到Oracle數據庫,並管理Oracle的Guid存儲,我需要一個SqlMapper.TypeHandler<Guid>。從數據庫加載Guid列時調用Parse方法,但是當我嘗試使用Guid參數執行SQL語句時,我得到以下異常:Dapper TypeHandler.SetValue()未被調用

System.ArgumentException未處理;消息=值在預期範圍內不會下降 .Source = Oracle.DataAccess。

在調試中,我可以看到我的處理程序的Parse()方法在從數據庫加載我的類時調用,但SetValue()方法不是。

的代碼重現異常低於


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<Guid> 
    { 
     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<Guid>(new GuidTypeHandler()); 
      var conn = new OracleConnection(Resources.ConnectionString); 
      var def = new CommandDefinition("select id, name from foo"); 

      conn.Open(); 

      var foo = conn.Query<Foo>(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(); 
     } 
    } 
} 
+0

你有沒有想過如何讓這個工作?當我嘗試將自定義對象數組傳遞給查詢時(例如,「SELECT * FROM myTable WHERE id = ANY(:ids)」和typeof(:ids)== typeof(myType []),我遇到了類似的問題。 )) – 2014-10-18 01:46:48

+0

沒有運氣,可能值得在Github上的Dapper問題列表中重新發布該查詢。 – Bertol 2014-10-19 06:46:18

回答

0

我工作圍繞這個問題寫圍繞.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<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(); 
    } 
} 

一個DTO類,它利用了包裝類:

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

注意我使用RAW (16)將它們存儲在Oracle中,而不是內置的Oracle Guid中。

編輯 看起來像這可能是一個錯誤,可能已被修復:https://github.com/StackExchange/dapper-dot-net/issues/253。看起來它並沒有進入NuGet包,所以我還沒有嘗試過。