Dapper 本身不支持动态建表等 DDL 操作,但可通过 Execute 执行原始 DDL 语句;需注意连接管理、SQL 注入防护、数据库语法差异及事务限制,生产环境推荐使用专业迁移工具。

Dapper 本身不支持数据库表的动态创建,它只是一个轻量级的 ORM 查询工具,专注于执行 DML(如 SELECT/INSERT/UPDATE/DELETE)和简单命令,不提供建表、改表等 DDL 操作的封装。但你可以用 Dapper 执行原始 DDL 语句(如 CREATE TABLE),前提是数据库驱动支持且你有对应权限。
直接用 Execute 执行 DDL 语句
Dapper 的 Execute 方法可以运行任意 SQL 字符串,包括 DDL。只要连接未关闭、事务允许、SQL 语法正确,就能生效。
- 确保连接是打开状态(Dapper 不会自动打开关闭连接)
- DDL 语句不能参数化(如
CREATE TABLE @tableName是非法的),必须拼接或使用白名单校验 - 不同数据库语法差异大(如 MySQL 的
ENGINE=InnoDB、SQL Server 的IDENTITY),需按目标数据库适配
示例(SQL Server):
string sql = @"CREATE TABLE Users (
Id INT IDENTITY(1,1) PRIMARY KEY,
Name NVARCHAR(50),
CreatedTime DATETIME2 DEFAULT GETDATE()
);";
connection.Execute(sql);
安全地动态建表(推荐做法)
避免字符串拼接导致 SQL 注入,尤其是表名/字段名来自用户输入时:
- 对标识符(表名、列名)使用数据库自带的转义函数,如 SQL Server 用
QUOTENAME(),PostgreSQL 用双引号"name",MySQL 用反引号`name` - 建立白名单机制:只允许预定义的表结构模板,通过配置或枚举选择,而非自由输入
- 建表前先检查表是否存在(如
IF NOT EXISTS),避免重复执行报错
SQL Server 示例(带存在性检查):
string tableName = "Logs";
string sql = $@"IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = {SqlMapper.QueryParameterName}tableName)
CREATE TABLE {SqlMapper.QuoteIdentifier(tableName)} (
Id INT IDENTITY(1,1) PRIMARY KEY,
Message NVARCHAR(MAX),
Timestamp DATETIME2 DEFAULT GETDATE()
);";
connection.Execute(sql, new { tableName });
结合实体类型自动生成建表语句(简易版)
你可以写一个辅助方法,根据 C# 类型反射出属性,生成基础 DDL。注意:这仅适用于简单场景,不处理外键、索引、约束等高级特性。
- 用
typeof(T).GetProperties()获取字段名和类型 - 映射 .NET 类型到数据库类型(如
string → NVARCHAR(100)、DateTime → DATETIME2) - 跳过复杂类型、集合、导航属性
- 仍需手动处理主键、自增、默认值等逻辑
小提示:这种“微型 Code-First”功能更建议交给 EF Core 或迁移工具(如 Flyway / Liquibase)来做,Dapper 定位不是替代它们。
注意事项和常见坑
- Dapper 不管理连接生命周期 —— DDL 执行失败可能导致连接中断,务必用
try/catch和显式Dispose - 某些数据库(如 SQLite)在事务中不允许 DDL;SQL Server 中 DDL 会隐式提交当前事务
- DDL 语句无法被 Dapper 的缓存或映射机制处理,
Query对建表语句无效 - 生产环境慎用动态建表 —— 应优先通过版本化迁移脚本管理 schema 变更
基本上就这些。Dapper 做 DDL 不是它的强项,但用好了很灵活;关键是要清楚边界,把建表逻辑控制住,别让它变成维护黑洞。









