Dapper 不自动处理数据库 DEFAULT 约束,需通过省略列名或显式写 DEFAULT 关键字来触发默认值;实体类中应避免传入 null 或空值,批量插入时需设为 DBNull.Value 或排除该列。

Dapper 本身不自动识别或处理数据库列的 DEFAULT 约束(比如 CREATE TABLE Users (Id INT IDENTITY, Name NVARCHAR(50), CreatedTime DATETIME2 DEFAULT GETDATE()) 中的 DEFAULT GETDATE()),它只是执行你写的 SQL。所以“插入时用数据库默认值”,关键在 SQL 写法 和 参数传入逻辑,而不是 Dapper 自动帮你跳过字段。
显式省略字段,让数据库生效
最常用也最可靠的方式:在 INSERT 语句中 根本不写带 DEFAULT 的列,数据库自然会填入默认值。
- ✅ 正确写法(假设
Status列有DEFAULT 'Pending'):INSERT INTO Orders (UserId, OrderNumber) VALUES (@UserId, @OrderNumber)
→Status字段没出现,SQL Server / PostgreSQL 等都会自动用默认值。 - ❌ 错误写法:
INSERT INTO Orders (UserId, OrderNumber, Status) VALUES (@UserId, @OrderNumber, @Status)
即使你传null或空字符串,只要写了这列,Dapper 就会把参数值塞进去——覆盖默认值。
用 DEFAULT 关键字显式指定
如果你必须在 SQL 中写出该列,又想强制走数据库默认值,可直接写 DEFAULT 字面量(注意不是参数):
- ✅ 支持写法(SQL Server / PostgreSQL 均支持):
INSERT INTO Orders (UserId, OrderNumber, Status) VALUES (@UserId, @OrderNumber, DEFAULT) - ⚠️ 注意:
不能写成@Status参数再赋值为DEFAULT—— 参数只能是值,不能是关键字;DEFAULT必须硬编码在 SQL 字符串里。
实体类中跳过属性映射
如果用对象传参(如 db.Execute(sql, order)),确保实体类中对应默认值的属性 不参与参数绑定:
- 推荐做法:实体类中该属性不加 public set,或用
[JsonIgnore]/ 自定义参数包装(如用DynamicParameters手动添加需要的字段); - 避免陷阱:不要给默认列属性赋
null、default(T)或空字符串,否则 Dapper 仍会把它当有效值传入。
批量插入(BulkCopy)时的默认值
使用 BulkCopy(如 Dapper.ProviderTools 或原生 SqlBulkCopy)时,默认值 默认不生效,因为它是绕过 SQL 引擎的底层导入。
- ✅ 解决方案:导入前先在 DataTable 或数据源中把默认列设为
DBNull.Value,并确保目标表列设置为AllowDBNull = true且有 DEFAULT; - ✅ 或者,在 BulkCopy 配置中启用
UseInternalTransaction并配合ColumnMappings明确排除该列(部分驱动支持)。
基本上就这些。核心就一条:Dapper 不干预 SQL 语义,想用数据库默认值,就得让 SQL 本身“不提供值”或“明确写 DEFAULT”。










