【问题标题】:How to deserialize DbString with Dapper如何使用 Dapper 反序列化 DbString
【发布时间】:2016-12-03 02:55:48
【问题描述】:

当我尝试反序列化包含DbString 表示的字符串的记录时:

class Record 
{
  public DbString Text {get; set;}
}

我得到错误

{"Invalid cast from 'System.String' to 'Dapper.DbString'."}

在这种情况下我是否误用了 DbString?

【问题讨论】:

    标签: c# string converter dapper


    【解决方案1】:

    Dapper 的想法是将查询结果转换为标准的 .net 类。

    “DbString”类型是一个 Dapper 类,用于以特定方式指定参数值,它不是“标准 .net”。

    因此,您应该从最简单的情况开始,而不是尝试猜测 Dapper 可能想要映射到的类型,因为 Dapper 通常会正常工作。

    在你的情况下,你的记录应该是

    class Record 
    {
        public string Text { get; set; }
    }
    

    Dapper 会做一些工作来确保处理任何合理的类型转换 - 例如,如果您的数据库字段是 int,那么它会很乐意将其映射到 C# 类型上的 int 属性或 到长 到短或字节(尽管如果强制转换为较小的数据类型,您会在运行时冒溢出异常的风险)。总而言之,Dapper 对你很好,并尝试做类型映射的艰苦工作——你通常可以坚持基础(字符串,而不用担心可能使用 DbString),Dapper 会帮你解决的!

    【讨论】:

    • 你下结论有点太快了,我的朋友。首先要提到的是——我们需要阅读和写作。我确实从使用一个简单的字符串开始。但是我们在任何地方使用 sql 数据提供程序,当将 DbParameter.Length 设置为 -1 时会引发异常(这与例如 OdbcParameter 不同,它可以正常工作)。所以我发现通过使用 DbString 我可以解决这个问题。
    • 我也考虑过仅在传递它们来编写查询时使用 DbString,但这意味着我必须手动创建参数对象,而不仅仅是传递我的记录。考虑到以上所有情况,如果我可以确认 DbString 旨在用作字段类型,我可以等待修复。否则,我可能会回到字符串+手动参数对象。
    【解决方案2】:

    如果您需要在读取模型中使用 DbString(如我的第一个答案的 cmets 中所述),那么您可以选择包含从字符串到 DbString 的映射器 - 例如。定义类

    public class DbStringTypeHandler : SqlMapper.TypeHandler<DbString>
    {
        public override DbString Parse(object value)
        {
            if (value == null)
                return null;
            var dbStringValue = value as DbString;
            if (dbStringValue != null)
                return dbStringValue;
            var stringValue = value as string;
            if (stringValue != null)
                return new DbString { Value = stringValue };
            throw new InvalidCastException("Invalid cast from '" + value.GetType() + "' to '" + typeof(DbString) + "'.");
        }
    
        public override void SetValue(IDbDataParameter parameter, DbString value)
        {
            parameter.Value = value;
        }
    }
    

    然后调用

    SqlMapper.AddTypeHandler<DbString>(new DbStringTypeHandler());
    

    在执行任何查询之前。

    现在,“Record”类应该可以很好地用作读取模型和“写入”(即设置参数)。

    我使用 SQL 服务器连接对此进行了测试,我认为它是“SqlMapper”类,无论您正在与哪个数据库交谈,您都需要调用“AddTypeHandler”,但有机会您需要根据提供者稍作调整。

    【讨论】:

    • 我觉得投反对票有点苛刻(与现在删除的评论有关,询问我为什么留下两个答案)!我认为,我最初的答案对最初(并且仍然是)陈述的原始问题有效;在大多数情况下,最好在 Record 类上使用“字符串”属性,而不是“DbString”。但是,当从新的角度考虑这个问题时(正如@ironic 在我的第一个答案中在 cmets 中澄清的那样),我的第二个(并且完全不同的)答案是适用的。
    • 以防万一 - 我没有否决你的答案!我什至会投票给他们,因为我很感激他们的帮助!
    • 谢谢。我认为有人在这个问题上做了一点打击 - 在看到我留下了其中两个并留下评论询问原因后,否决了答案。当我回复解释时,他们删除了他们的评论,但留下了反对票。我很感激你纠正了平衡! :)
    • 这就是我所需要的。我只需要添加 DbString.Length 属性读取/写入。
    猜你喜欢
    • 2020-11-05
    • 2012-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-20
    • 1970-01-01
    • 2021-11-28
    • 1970-01-01
    相关资源
    最近更新 更多