Skip to main content

One post tagged with "ORM"

View All Tags

· 3 min read
Alec.Ji

使用 Dapper 时,有没有遇到过类似的错误

A parameterless default constructor or one matching signature (System.Int32 CustomerID, System.String CustomerName, System.Int32 X) is required for XXX materialization

TL;DR

这是由于目标类 存在含参构造函数ctorA不存在 不含参的构造函数ctorA 与查询结果不一致(参数个数或参数类型)

问题产生

同事正常做功能迭代,已有查询多返回一个字段,改动如下

public class A{
public A(int a,
string b,
+ XXTypeEnum type
)
{
A = a;
B = b;
+ Type = type
}
}
...
var sql = @"SELECT A,
B,
+Type
FROM
...
var result = await connection.Query<A>(sql);

然后就产生了上边类似的报错

A parameterless default constructor or one matching signature (System.Int32 A, System.String C, System.SByte Type) is required for A materialization

问题分析

查了一下这个异常,说明很简单 需要一个无参的构造函数 或者 一个匹配签名的构造函数

,加一个空的构造函数试了的确是可以,但是为什么如此呢,看着现有的构造函数也是匹配的,仔细看下Type参数的类型并不匹配

debug 几次,得出如下结果

  • 不存在无参构造函数,自动映射(显式转换(比如 int -> enum))
  • 存在含参构造函数,查找对应类型,对应参数的构造函数(此处不会默认显式转换,比如枚举)
  • 存在无参构造函数,无参构造函数会正常调用,但是以最终映射为准

结论

对于 Dapper 对应结果 Model类, 最好是不写含参ctor,如果写了含参的ctor 也要写一个 不含参的ctor(private 也可以)

ps. 使用Mysql 数据库,系统枚举值使用了 tinyint(4)GetFieldType 结果为 System.SByte,附一个 tinyint 类型对应

mysql TypeFieldType
tinyint(1)System.Boolean
*可以通过修改连接字符串 TreatTinyAsBoolean=false 为System.SByte
tinyintSystem.SByte
tinyint unsignedSystem.Byte

pps. 8.0.17 中已弃用整数数据类型的显示宽度 , tinyint(1) 除外,所以最好不要用tinyint(x)的写法 具体可看mysql 8.0.19 feature

REF