Dapper 不封装数据库函数但支持在 SQL 中直接调用,需通过参数化传递值、硬编码函数名,UDF 按标量或表值选择 QuerySingle 或 Query,异常由 ADO.NET 原样抛出。

Dapper 本身不提供专门封装数据库函数(如 SQL Server 的 GETDATE()、MySQL 的 NOW() 或自定义 UDF)的 API,但它完全支持在 SQL 语句中直接调用——只要你的数据库驱动(如 SqlClient、MySqlConnector、Npgsql)能执行该语句,Dapper 就能跑。
直接在 SQL 中写函数调用
这是最常用也最推荐的方式。UDF 和系统函数一样,属于 SQL 表达式的一部分,Dapper 只负责把 SQL 交给 ADO.NET 执行。
- 查询时嵌入函数:比如获取当前时间 + 计算字段
var sql = "SELECT Id, Name, DATEDIFF(day, CreatedTime, GETDATE()) AS DaysAgo FROM Users WHERE Status = @status";
var users = connection.Query
- 插入/更新时调用 UDF:比如用自定义函数生成编码
var sql = "INSERT INTO Orders (OrderNo, Amount) VALUES (dbo.GenOrderNo(), @amount)";
connection.Execute(sql, new { amount = 99.9m });
注意 UDF 参数和返回值类型匹配
UDF 若带参数,必须确保传入值类型与数据库定义一致;若返回表值(TVF),要用 Query;若返回标量,可用 QuerySingle 或 ExecuteScalar()。
- 标量 UDF 示例(SQL Server):
SELECT dbo.CalculateTax(@amount, 'CN') - 表值 UDF 示例:
SELECT * FROM dbo.GetUsersByDept(@deptId)→ 对应Query() - MySQL 自定义函数同理,如
SELECT my_udf_upper(name) FROM users
避免在 C# 端拼接函数名或参数名
不要用字符串拼接构造函数调用,尤其涉及 UDF 名称或 schema(如 dbo.fn_xxx)。这容易引发 SQL 注入或权限问题。所有动态部分应通过参数化(@param)传递,函数名和结构应硬编码或从白名单读取。
- ✅ 安全:
"SELECT * FROM dbo.GetUserById(@id)" - ❌ 危险:
$"SELECT * FROM {schema}.{udfName}(@id)"
特殊场景:需要捕获函数执行状态或错误
UDF 抛异常时,Dapper 会原样抛出 ADO.NET 异常(如 SqlException)。你可以用 try/catch 捕获,并检查 Number 或 Message 判断是否为 UDF 内部逻辑错误。
- 例如 SQL Server 中 UDF 抛出
RAISERROR,会触发SqlException - 建议在 UDF 内部尽量用 RETURN 值代替异常,更利于 Dapper 统一处理
基本上就这些。Dapper 对函数的支持就是“透明”的——它不干预 SQL,只专注映射结果。你写得对,它就跑得通。










