ORMX 内置函数概述 - 学习教程,:内置函数,Extension, Function, 字符串函数,数学函数,日期函数,数据库函数 - 学习 ORMX 的内置函数功能,包括字符串函数、数学函数、日期函数等,以及如何使用 Extension 方法在查询中使用数据库函数。

您当前正在浏览的是本站SEO版网页

请点击确认

马上提升浏览体验

ORMX 内置函数概述

编程 数据库 阅读:0
5/4/2026 3:25:00 PM

学习 ORMX 的内置函数功能,包括字符串函数、数学函数、日期函数等,以及如何使用 Extension 方法在查询中使用数据库函数。 关键字:内置函数,Extension, Function, 字符串函数,数学函数,日期函数,数据库函数

内置函数概述

ORMX 提供了丰富的内置函数支持,允许在查询中直接使用数据库提供的函数。这些函数包括字符串函数、数学函数、日期函数、加密函数等。通过 Extension<TFunc> 方法,可以灵活地在 SELECT 子句中使用这些函数。

Function 类

Function<T> 类是 ORMX 中用于表示数据库函数的核心类。

基本用法

// 创建 Function 对象
var upperFunc = new Function<User>("UPPER", u => u.Username);

// 使用 WithAlias 设置别名
var upperFuncWithAlias = new Function<User>("UPPER", u => u.Username)
    .WithAlias("UpperName");

// 使用 WithDistinct 设置 DISTINCT
var distinctFunc = new Function<User>("UPPER", u => u.Username)
    .WithDistinct();

构造函数参数说明

  • functionName: 数据库函数名称(如 "UPPER", "CONCAT", "NOW" 等)
  • expression: Lambda 表达式,指定函数的参数
  • Alias: 可选,函数结果的列别名
  • IsDistinct: 可选,是否添加 DISTINCT 修饰符

常用内置函数

字符串函数

UPPER - 转换为大写

string generatedSql = "";
object?[] parameters = Array.Empty<object?>();

_tableManager.Table<User>()
    .Extension((extObj) =>
    {
        generatedSql = extObj.Query;
        parameters = extObj.Parameters;
    })
    .Extension(new Function<User>("UPPER", m => m.Username)
        .WithAlias("UpperName"))
    .Where(u => u.Id == 1)
    .GetList();

// MySQL: SELECT UPPER(`Username`) AS `UpperName` FROM `Users` WHERE `Id` = @p0
// SQL Server: SELECT UPPER([Username]) AS [UpperName] FROM [Users] WHERE [Id] = @p0
// PostgreSQL: SELECT UPPER("Username") AS "UpperName" FROM "Users" WHERE "Id" = @p0

LOWER - 转换为小写

_tableManager.Table<User>()
    .Extension(new Function<User>("LOWER", m => m.Username)
        .WithAlias("LowerName"))
    .Where(u => u.Id == 2)
    .GetList();

// MySQL: SELECT LOWER(`Username`) AS `LowerName` FROM `Users` WHERE `Id` = @p0
// SQL Server: SELECT LOWER([Username]) AS [LowerName] FROM [Users] WHERE [Id] = @p0

CONCAT - 字符串连接

// 连接多个字段
_tableManager.Table<User>()
    .Extension(new Function<User>("CONCAT", m => new { m.Username, m.Email })
        .WithAlias("FullInfo"))
    .Where(u => u.Id == 1)
    .GetList();

// MySQL: SELECT CONCAT(`Username`, `Email`) AS `FullInfo` FROM `Users` WHERE `Id` = @p0
// SQL Server: SELECT CONCAT([Username], [Email]) AS [FullInfo] FROM [Users] WHERE [Id` = @p0
// SQLite: SELECT "Username" || "Email" AS "FullInfo" FROM "Users" WHERE "Id" = @p0

注意:SQLite 不支持 CONCAT 函数,会自动转换为 || 运算符。

LENGTH/LEN - 字符串长度

_tableManager.Table<User>()
    .Extension(new Function<User>("LENGTH", m => m.Email)
        .WithAlias("EmailLength"))
    .Where(u => u.Id == 3)
    .GetList();

// MySQL: SELECT LENGTH(`Email`) AS `EmailLength` FROM `Users` WHERE `Id` = @p0
// SQL Server: SELECT LEN([Email]) AS [EmailLength] FROM [Users] WHERE [Id] = @p0
// PostgreSQL: SELECT LENGTH("Email") AS "EmailLength" FROM "Users" WHERE "Id" = @p0

注意:SQL Server 使用 LEN 函数,其他数据库使用 LENGTH

数学函数

ABS - 绝对值

_tableManager.Table<User>()
    .Extension(new Function<User>("ABS", m => m.Salary)
        .WithAlias("AbsSalary"))
    .Where(u => u.Id == 1)
    .GetList();

// MySQL: SELECT ABS(`Salary`) AS `AbsSalary` FROM `Users` WHERE `Id` = @p0
// SQL Server: SELECT ABS([Salary]) AS [AbsSalary] FROM [Users] WHERE [Id] = @p0

ROUND - 四舍五入

// 传递多个参数
_tableManager.Table<User>()
    .Extension(new Function<User>("ROUND", m => new { p0 = m.Salary, p1 = 0 })
        .WithAlias("RoundedSalary"))
    .Where(u => u.Id == 2)
    .GetList();

// MySQL: SELECT ROUND(`Salary`, 0) AS `RoundedSalary` FROM `Users` WHERE `Id` = @p0
// SQL Server: SELECT ROUND([Salary], 0) AS [RoundedSalary] FROM [Users] WHERE [Id] = @p0

日期函数

NOW - 当前时间

_tableManager.Table<User>()
    .Extension(new Function<User>("NOW", m => m.Id)
        .WithAlias("CurrentTime"))
    .Where(u => u.Id == 1)
    .GetList();

// MySQL: SELECT NOW() AS `CurrentTime` FROM `Users` WHERE `Id` = @p0
// SQL Server: SELECT GETDATE() AS [CurrentTime] FROM [Users] WHERE [Id] = @p0
// SQLite: SELECT datetime('now') AS "CurrentTime" FROM "Users" WHERE "Id" = @p0
// PostgreSQL: SELECT NOW() AS "CurrentTime" FROM "Users" WHERE "Id" = @p0

注意:不同数据库的当前时间函数不同:

  • MySQL/PostgreSQL: NOW()
  • SQL Server: GETDATE()
  • SQLite: datetime('now')

ORMX 会自动根据数据库类型生成正确的 SQL。

其他函数

COALESCE - 返回第一个非空值

_tableManager.Table<User>()
    .Extension(new Function<User>("COALESCE", m => new { p0 = m.Phone, p1 = 0 })
        .WithAlias("PhoneOrZero"))
    .Where(u => u.Id == 1)
    .GetList();

// MySQL: SELECT COALESCE(`Phone`, 0) AS `PhoneOrZero` FROM `Users` WHERE `Id` = @p0
// SQL Server: SELECT COALESCE([Phone], 0) AS [PhoneOrZero] FROM [Users] WHERE [Id] = @p0

MD5 - 哈希函数(部分数据库支持)

_tableManager.Table<User>()
    .Extension(new Function<User>("MD5", m => m.Email + m.Username)
        .WithAlias("EmailHash"))
    .Where(u => u.Id == 1)
    .GetList();

// MySQL: SELECT MD5(`Email` + `Username`) AS `EmailHash` FROM `Users` WHERE `Id` = @p0
// PostgreSQL: SELECT MD5("Email" || "Username") AS "EmailHash" FROM "Users" WHERE "Id" = @p0

注意

  • SQLite 不支持 MD5 函数
  • SQL Server 需要使用 HASHBYTES('MD5', expression) 语法,当前版本暂不支持
  • PostgreSQL 使用 || 运算符连接字符串

数据库差异处理

ORMX 会自动处理不同数据库之间的函数差异:

字符串连接运算符

  • MySQL/SQL Server: 使用 +CONCAT 函数
  • PostgreSQL/SQLite: 使用 || 运算符
// PostgreSQL 会自动转换为 ||
new Function<User>("MD5", m => m.Email + m.Username)
// PostgreSQL: MD5("Email" || "Username")
// MySQL: MD5(`Email` + `Username`)

函数名称差异

  • 字符串长度: MySQL/PostgreSQL 使用 LENGTH,SQL Server 使用 LEN
  • 当前时间: MySQL/PostgreSQL 使用 NOW,SQL Server 使用 GETDATE,SQLite 使用 datetime('now')

ORMX 会根据数据库类型自动生成正确的函数名称。

在 UNION 查询中使用函数

Extension<TFunc> 方法可以在 UNION 查询的子查询中使用:

// 在每个 UNION 子查询内部使用 Extension 添加 Function
var result = _tableManager.UnionTable<User>(qb => qb
    .Extension(new Function<User>("UPPER", u => u.Username))
    .Where(u => u.Age > 30))
    .UnionAll<User>(qb => qb
        .Extension(new Function<User>("UPPER", u => u.Username))
        .Where(u => u.Username == "Alice"))
    .GetList();

// MySQL: 
// SELECT UPPER(`Username`) FROM `Users` WHERE `Age` > @p0 
// UNION ALL 
// SELECT UPPER(`Username`) FROM `Users` WHERE `Username` = @p1

重要提示

  • Function 应该在 UNION 的每个子查询内部使用 Extension 添加
  • 不支持在 UNION 之后使用 UnionExtension<TFunc> 添加 Function
  • 所有 UNION 子查询的 SELECT 列必须匹配

实际应用示例

用户信息格式化

// 将用户名转换为大写,并连接邮箱
var users = tableManager.Table<User>()
    .Extension(new Function<User>("UPPER", u => u.Username)
        .WithAlias("UpperName"))
    .Extension(new Function<User>("CONCAT", u => new { u.Username, u.Email })
        .WithAlias("FullInfo"))
    .GetList();

foreach (var user in users)
{
    Console.WriteLine(<div class="latex">$"大写用户名:{user.UpperName}");
    Console.WriteLine($</div>"完整信息:{user.FullInfo}");
}

数据脱敏处理

// 使用 MD5 对邮箱进行哈希处理
var users = tableManager.Table<User>()
    .Extension(new Function<User>("MD5", u => u.Email)
        .WithAlias("EmailHash"))
    .GetList();

foreach (var user in users)
{
    Console.WriteLine(<div class="latex">$"邮箱哈希:{user.EmailHash}");
}

数值格式化

// 对工资进行四舍五入
var users = tableManager.Table<User>()
    .Extension(new Function<User>("ROUND", u => new { p0 = u.Salary, p1 = 0 })
        .WithAlias("RoundedSalary"))
    .GetList();

foreach (var user in users)
{
    Console.WriteLine($</div>"格式化工资:{user.RoundedSalary}");
}

时间戳处理

// 获取当前时间
var result = tableManager.Table<User>()
    .Extension(new Function<User>("NOW", u => u.Id)
        .WithAlias("CurrentTime"))
    .Where(u => u.Id == 1)
    .GetList();

Console.WriteLine($"查询时间:{result[0].CurrentTime}");

最佳实践

1. 使用有意义的别名

// 好的做法
.Extension(new Function<User>("UPPER", u => u.Username)
    .WithAlias("UpperName"))

// 不推荐:没有别名
.Extension(new Function<User>("UPPER", u => u.Username))

2. 注意数据库兼容性

// 检查数据库类型,选择支持的函数
if (dbProvider.DatabaseType == DatabaseType.SQLServer)
{
    // SQL Server 特定的处理
}
else
{
    // 其他数据库的处理
}

3. 处理字符串连接

// ORMX 会自动处理不同数据库的字符串连接运算符
new Function<User>("CONCAT", m => new { m.Username, m.Email })
// 在 SQLite/PostgreSQL 中会自动转换为 || 运算符

4. 多参数函数的使用

// 使用匿名对象传递多个参数
new Function<User>("ROUND", m => new { p0 = m.Salary, p1 = 0 })
// 会被转换为:ROUND(Salary, 0)

5. 在复杂查询中使用

// 结合 WHERE、ORDER BY 等使用
var result = tableManager.Table<User>()
    .Extension(new Function<User>("LENGTH", u => u.Email)
        .WithAlias("EmailLength"))
    .Where(u => u.Age > 18)
    .OrderByDesc(u => u.EmailLength)
    .Limit(10)
    .GetList();

支持的函数列表

字符串函数

  • UPPER - 转换为大写
  • LOWER - 转换为小写
  • CONCAT - 字符串连接(SQLite 自动转换为 ||
  • LENGTH / LEN - 字符串长度(SQL Server 使用 LEN)
  • MD5 - MD5 哈希(SQLite/SQLServer 不支持)

数学函数

  • ABS - 绝对值
  • ROUND - 四舍五入

日期函数

  • NOW - 当前时间(各数据库实现不同)

其他函数

  • COALESCE - 返回第一个非空值

注意事项

  1. 数据库兼容性:不是所有函数在所有数据库中都受支持
  2. 参数类型:确保传递给函数的参数类型正确
  3. 性能考虑:在大数据量场景下,函数计算可能影响性能
  4. 结果映射:使用 WithAlias 确保结果能正确映射到属性
  5. NULL 值处理:大多数函数会忽略 NULL 值

总结

ORMX 的内置函数功能允许在查询中直接使用数据库提供的各种函数。通过 Extension<TFunc> 方法,可以灵活地使用字符串函数、数学函数、日期函数等。ORMX 会自动处理不同数据库之间的差异,生成正确的 SQL 语句。在实际应用中,合理使用内置函数可以简化数据处理逻辑,提高开发效率。

扩展思考

对于 ORMX 未直接支持的数据库函数,如何使用 Extension<Action<ExtensionObject>> 方法直接编写 SQL?如何处理自定义函数的返回值映射?在分布式数据库场景下,如何确保函数在所有节点上都可用?这些问题值得在深入使用 ORMX 后进一步探索。