前言
有些数据库的函数在.Net中有对应的函数映射,但是其中一些是没有的,这样子做是为了保持实体框架API在不同的数据库提供程序之间保持一致。
但是你可以编写代码来补充,通过注册函数,可以在EFCore中来使用数据库的函数。
内置函数
支持通过修改数据库上下文来增加对数据库内置函数的调用, 举例以使用pgsql的内置函数to_char为例,我们有一个数据库上下文OpenDbContext,修改增加如下方法
请注意,我们没有实现方法,我们只是提供了正确的签名
/// <summary>
/// pg to_char内置函数
/// </summary>
/// <param name="input">要转换的值</param>
/// <param name="format">转换的格式</param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
[DbFunction(Name = "to_char", IsBuiltIn = true, IsNullable = false)]
public static string ToChar(DateTime input, string format = "yyyy-MM-dd HH24:mi:ss")
{
throw new NotImplementedException();
}
IsBuiltIn指是否为内置函数 IsNullable指是否可以为null
然后我一个简单的查询操作
[HttpGet("time/tochar")]
public async Task<string> TimeToChar()
{
var list = await _openDbContext.Users
.Select(t => OpenDbContext.ToChar(t.CreateTime, "yyyy-MM-dd HH24:mi:ss"))
.ToListAsync();
return "success";
}
执行查询的时候,会生成以下SQL语句
SELECT to_char(u.create_time, 'yyyy-MM-dd HH24:mi:ss')
FROM sample."user" AS u
自定义函数
除了可以使用内置函数以外,还可以创建自己的sql函数并且以这种方式进行添加,下面使用pgsql创建一个简单的数据库函数
CREATE OR REPLACE FUNCTION sample.add_credit(source_credit double precision, addCredit int4)
RETURNS double precision AS
$$
SELECT source_credit + addCredit;
$$
LANGUAGE SQL;
现在还在数据库上下文中注册
/// <summary>
/// 添加学分的自定义函数
/// </summary>
/// <param name="sourceCredit">原始学分</param>
/// <param name="addCredit">要添加的学分</param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
[DbFunction(Name = "add_credit", Schema = "sample", IsBuiltIn = false)]
public static double AddCredit(double sourceCredit, int addCredit)
{
throw new NotImplementedException();
}
然后我编写一个简单的查询操作
/// <summary>
/// 学分相加
/// </summary>
/// <returns></returns>
[HttpGet("double/tochar")]
public async Task<string> DoubleAdd()
{
var list = await _openDbContext.Users
.Select(t => OpenDbContext.AddCredit(t.Credit, 10))
.ToListAsync();
return "success";
}
执行查询的时候,会生成以下SQL语句
SELECT sample.add_credit(u.credit, 10)
FROM sample."user" AS u
总结
使用 DbFunctions 是一种在EFCore查询中利用特定数据库功能的有用方法,但是需要注意。因为您正在使用数据库特定的功能,所以如果您想这样做,后期考虑移植到其他数据库就会变得更加困难。
参考文档
docs:https://docs.microsoft.com/zh-cn/ef/core/querying/database-functions
数据库函数:https://timdeschryver.dev/blog/consuming-sql-functions-with-entity-framework