首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >列中空值的Dapper强制转换异常

列中空值的Dapper强制转换异常
EN

Stack Overflow用户
提问于 2018-01-09 16:04:56
回答 3查看 4.4K关注 0票数 8

我使用SQLite和它的闭包扩展来存储层次结构。非闭包表创建为

代码语言:javascript
运行
复制
_connection.Execute(@"CREATE TABLE IF NOT EXISTS category (
    id INTEGER NOT NULL PRIMARY KEY,
    name TEXT,
    parent_id INTEGER,
    FOREIGN KEY (parent_id) REFERENCES category (id)
);");

插入根节点时,parent_id设置为NULL。用于Dapper的往返于is的类。

代码语言:javascript
运行
复制
public class TestRecord
{
    public long id;
    public string name;
    public long? parent_id;
}

在我看来,Dapper在读取根节点或非根节点时不会遇到任何问题,因为所讨论的列显然是可空的。但是,查询所有条目如下:

代码语言:javascript
运行
复制
_connection.Query<TestRecord>(@"SELECT * FROM category;");

将抛出根节点,因为它不能转换某些内容(这很奇怪,因为在任何地方都不涉及32位ints ):

代码语言:javascript
运行
复制
Unhandled Exception: System.Data.DataException: 
Error parsing column 2 (parent_id=1 - Int64) ---> 
System.InvalidCastException: Unable to cast object of type 'System.Int64' to type 
  'System.Int32'.

返回正确结果的解决方案是

代码语言:javascript
运行
复制
.Query<TestRecord>(@"SELECT id, IFNULL(parent_id, 0), name FROM category;");

但这是不允许的,有几个原因。我特别不想列出查询中的所有列,也不想介绍parent_id的特例。

不使用Dapper并手动映射它与原始查询非常好,对于sqlite当然也是如此。

那么,我如何让Dapper接受并映射正确的条目呢?

编辑:我正在使用Dapper1.50.4和DotNetCore2.0。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-01-19 17:14:14

根据马克的评论,这种情况不应该发生,而且它会警告库修复。这个问题正在被这里跟踪,也影响到其他人。

票数 2
EN

Stack Overflow用户

发布于 2019-02-14 15:26:17

sqlite可空类型的解决方案。链接

代码语言:javascript
运行
复制
public class NullableLongHandler : SqlMapper.TypeHandler<long?>
{
    public override void SetValue(IDbDataParameter parameter, long? value)
    {
        if (value.HasValue)
            parameter.Value = value.Value;
        else
            parameter.Value = DBNull.Value;
    }

    public override long? Parse(object value)
    {
        if (value == null || value is DBNull) return null;
        return Convert.ToInt64(value);
    }
}

代码语言:javascript
运行
复制
SqlMapper.AddTypeHandler(new NullableLongHandler());
票数 2
EN

Stack Overflow用户

发布于 2018-01-19 16:05:01

如果您使用"INTEGER“创建表,Sqlite将创建int32,但是您的模型中有一个long,我猜这是一个无效的强制转换异常,必须使用BigInt来提供long。

因此,您应该将请求更改为:

代码语言:javascript
运行
复制
_connection.Execute(@"CREATE TABLE IF NOT EXISTS category (
  id BIGINT NOT NULL PRIMARY KEY,
  name TEXT,
  parent_id BIGINT,
  FOREIGN KEY (parent_id) REFERENCES category (id)
);");

或者使用与请求匹配的模型:

代码语言:javascript
运行
复制
public class TestRecord
{
    public int id;
    public string name;
    public int? parent_id;
}

我猜您使用"IFNULL(parent_id,0)“的请求是有效的,因为它包含一个强制转换,因为0可以被认为是int32。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48172218

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档