小巧玲珑TypeHandler.SetValue()不会被调用 [英] Dapper TypeHandler.SetValue() not being called

查看:295
本文介绍了小巧玲珑TypeHandler.SetValue()不会被调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我测试小巧玲珑的加载/对象持久化到Oracle数据库,并管理Oracle的GUID存储我需要一个 SqlMapper.TypeHandler<&的Guid GT; 。当装载从数据库GUID列Parse方法被调用,但是当我尝试使用GUID参数,我得到了以下异常执行SQL语句:




System.ArgumentException了未处理;消息=值没有在预期的range.Source = Oracle.DataAccess。





在调试,我可以看到从数据库加载我上课的时候被调用我的处理程序的parse()方法,但的SetValue()mdethod不是。



再现异常的代码如下






  CREATE TABLE富(ID RAW(16)NOT NULL PRIMARY KEY,
名称VARCHAR2(30)NOT NULL);

插入到foo(ID,姓名)VALUES(SYS_GUID(),'酒吧');

COMMIT;






 使用系统; 
使用System.Linq的;
采用精致小巧;
使用Oracle.DataAccess.Client;

计划命名空间
{
公共类Foo
{
公众的Guid标识{搞定;组; }
公共字符串名称{;组; }
}

类GuidTypeHandler:SqlMapper.TypeHandler<&的Guid GT;
{
公众覆盖的Guid解析(对象的值)
{
Console.WriteLine(处理{0}的解析,值);

VAR inVal =(字节[])值;
字节[] outVal =新字节[] {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]};
返回新的GUID(outVal);
}

公共覆盖无效的SetValue(System.Data.IDbDataParameter参数,GUID值)
{
Console.WriteLine(处理的SETVALUE {0},值);

VAR inVal = value.ToByteArray();
字节[] outVal =新字节[] {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;
}
}

类节目
{
静态无效的主要(字串[] args)
{
SqlMapper.AddTypeHandler< ;的Guid>(新GuidTypeHandler());
变种康恩=新的OracleConnection(Resources.ConnectionString);
变种高清=新CommandDefinition(SELECT标识,从foo的名字);

conn.Open();

无功富= conn.Query<富>(DEF)。首先();
Console.WriteLine(foo.Id +,+ foo.Name);

foo.Name =新酒吧;

=高清新CommandDefinition(
UPDATE富集名称=:名称,其中ID =:ID,
参数:新{ID = foo.Id,NAME = foo的。名称 });

无功行= conn.Execute(DEF);
Console.WriteLine({0}插入行,行);

到Console.ReadLine();
}
}
}


解决方案

我的工作解决此问题通过写围绕.NET的Guid类的包装。不理想的,因为你最终在你的DTO类包装,但它的作品。



包装类:

 公共类OracleGuid 
{
私人的Guid dotNetGuid;

公共OracleGuid(GUID GUID)
{
this.dotNetGuid = GUID;
}

公共OracleGuid(字节[]的字节数组)
{
this.dotNetGuid =新的GUID(字节阵列);

}

公众的Guid InternalGuid {{返回dotNetGuid; }}
}

的处理程序类:

 公共类OracleGuidHandler:SqlMapper.TypeHandler< OracleGuid> 
{
公众覆盖OracleGuid解析(对象的值)
{
返回新OracleGuid((字节[])值);
}

公共覆盖无效的SetValue(System.Data.IDbDataParameter参数,OracleGuid值)
{
parameter.Value = value.InternalGuid.ToByteArray();
}
}

一个DTO类,它利用了包装类:

 公共类FooDto 
{
公共OracleGuid标识{搞定;组; }
公共字符串名称{;组; }
}

请注意,我使用RAW(16)来存储这些在Oracle中, ,没有内置在Oracle中的GUID



修改
看起来这可能是一个错误,可能已得到修复:<一HREF =https://github.com/StackExchange/dapper-dot-net/issues/253相对=nofollow> https://github.com/StackExchange/dapper-dot-net/issues/253 。看起来并不像它已经做了它成的NuGet包尚未所以我还没有尝试过了呢。


I am testing Dapper to load / persist objects to an Oracle database, and to manage Oracle's Guid storage I need a SqlMapper.TypeHandler<Guid>. When loading a Guid column from the database the Parse method is called, but when I attempt to execute an SQL statement using a Guid parameter I get the following exception:

System.ArgumentException was unhandled; Message=Value does not fall within the expected range.Source=Oracle.DataAccess.

In debug I can see that my handler's Parse() method is being called when loading my class from the database, but the SetValue() mdethod is not.

The code to reproduce the exception is below


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

解决方案

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.

这篇关于小巧玲珑TypeHandler.SetValue()不会被调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆