gpt4 book ai didi

c# - Dapper TypeHandler.SetValue() 未被调用

转载 作者:太空狗 更新时间:2023-10-29 19:46:58 28 4
gpt4 key购买 nike

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

System.ArgumentException was unhandled; Message=Value does not fall within the expected range.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();
}
}
}

最佳答案

如果其他人偶然发现这篇文章并遇到类似问题,我找到了一个无需包装器即可处理 Guid 的解决方案。

Dapper 中的问题在于 Dapper 搜索匹配的 DbTypeTypeHandler 实现的顺序。 Dapper 更喜欢“本地”DbType 作为 Guid(在 SqlMapper#LookupDbType 中)。为了使 Dapper 使用您自己的实现,除了添加您自己的 TypeHandler 之外,您还必须删除默认映射:

SqlMapper.AddTypeHandler<Guid>(new GuidTypeHandler());
SqlMapper.RemoveTypeMap(typeof(Guid));
SqlMapper.RemoveTypeMap(typeof(Guid?));

我目前在使用 SQLite 时使用基于 string 的实现:

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

关于c# - Dapper TypeHandler.SetValue() 未被调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25568657/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com