我使用SQLite和它的闭包扩展来存储层次结构。非闭包表创建为
_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的类。
public class TestRecord
{
public long id;
public string name;
public long? parent_id;
}
在我看来,Dapper在读取根节点或非根节点时不会遇到任何问题,因为所讨论的列显然是可空的。但是,查询所有条目如下:
_connection.Query<TestRecord>(@"SELECT * FROM category;");
将抛出根节点,因为它不能转换某些内容(这很奇怪,因为在任何地方都不涉及32位ints ):
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'.
返回正确结果的解决方案是
.Query<TestRecord>(@"SELECT id, IFNULL(parent_id, 0), name FROM category;");
但这是不允许的,有几个原因。我特别不想列出查询中的所有列,也不想介绍parent_id
的特例。
不使用Dapper并手动映射它与原始查询非常好,对于sqlite当然也是如此。
那么,我如何让Dapper接受并映射正确的条目呢?
编辑:我正在使用Dapper1.50.4和DotNetCore2.0。
发布于 2018-01-19 16:05:01
如果您使用"INTEGER“创建表,Sqlite将创建int32,但是您的模型中有一个long,我猜这是一个无效的强制转换异常,必须使用BigInt来提供long。
因此,您应该将请求更改为:
_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)
);");
或者使用与请求匹配的模型:
public class TestRecord
{
public int id;
public string name;
public int? parent_id;
}
我猜您使用"IFNULL(parent_id,0)“的请求是有效的,因为它包含一个强制转换,因为0可以被认为是int32。
https://stackoverflow.com/questions/48172218
复制相似问题