学习ORMX的高级功能,包括多数据库支持、SQL执行器接口、表管理器接口、SQL调试功能、资源释放和窗口函数等高级特性。 关键字:高级功能, 多数据库支持, SQL执行器, 表管理器, SQL调试, 资源释放, 窗口函数
第十一章:高级功能
11.1 多数据库支持
11.1.1 支持的数据库类型
ORMX 支持以下主流数据库:
- SQLite - 轻量级嵌入式数据库
- MySQL - 流行的开源关系数据库
- PostgreSQL - 功能强大的开源对象关系数据库
- SQL Server - 微软企业级关系数据库
- MongoDB - 面向文档的 NoSQL 数据库(支持事务和 ACID 特性)
- Rides - 高性能分布式数据库(兼容 MySQL 协议)
11.1.2 数据库提供程序接口
IDbProvider 接口定义了数据库提供程序的核心功能:
public interface IDbProvider
{
// 获取自增ID的SQL查询
string IdentitySelectQuery { get; }
// 生成分页查询
string BuildPagedQuery(string query, int pageNumber, int pageSize);
// 获取参数前缀
string ParameterPrefix { get; }
// 格式化表名
string FormatTableName(string tableName);
// 格式化列名
string FormatColumnName(string columnName);
// 创建类型映射器
IDbTypeMapper CreateTypeMapper();
// 创建表管理器
ITableManager GetTableManager(DbConnection connection, ISqlExecutor sqlExecutor);
}
11.1.3 数据库提供程序使用示例
ORMX 提供了两种连接管理方式,推荐使用方式一(传入连接字符串)。
方式一:传入连接字符串(推荐)
using JCode.ORMX.DataProviders.SQLite;
// 创建数据库提供程序(内部自动创建连接)
using var provider = new SqliteDatabaseProvider("Data Source=:memory:");
// 获取表管理器(无需额外参数)
var tableManager = provider.GetTableManager();
// 获取表对象
var userTable = tableManager.Table<User>();
方式二:传入已创建的连接实例
using JCode.ORMX.DataProviders.SQLite;
using Microsoft.Data.Sqlite;
// 创建数据库连接
using var connection = new SqliteConnection("Data Source=:memory:");
connection.Open();
// 创建数据库提供程序
using var provider = new SqliteDatabaseProvider(connection);
// 获取表管理器
var tableManager = provider.GetTableManager();
// 获取表对象
var userTable = tableManager.Table<User>();
SQLite 连接字符串:
// 内存数据库
"Data Source=:memory:"
// 文件数据库
"Data Source=mydatabase.db"
// 带密码的数据库
"Data Source=mydatabase.db;Password=mypassword;"
MongoDB 提供程序使用示例:
using JCode.ORMX.DbProvider.MongoDB;
// 创建 MongoDB 提供程序(使用单个节点)
using var provider = new MongoDBProvider("mongodb://localhost:27017", "mydb");
// 获取表管理器
var tableManager = provider.GetTableManager();
// 获取表对象
var userTable = tableManager.Table<User>();
MongoDB 副本集连接:
using JCode.ORMX.DbProvider.MongoDB;
// 创建 MongoDB 提供程序(使用副本集)
using var provider = new MongoDBProvider(
"mongodb://host1:27017,host2:27017,host3:27017/?replicaSet=myReplicaSet",
"mydb"
);
// 获取表管理器
var tableManager = provider.GetTableManager();
MongoDB 连接字符串:
// 单个节点
"mongodb://localhost:27017"
// 副本集
"mongodb://host1:27017,host2:27017,host3:27017/?replicaSet=myReplicaSet"
// 带认证
"mongodb://username:password@localhost:27017"
// 带认证和数据库
"mongodb://username:password@localhost:27017/mydb"
// 带连接选项
"mongodb://localhost:27017/?connectTimeoutMS=30000&socketTimeoutMS=30000"
数据库提供程序的主要方法:
SQLite 提供程序:
public class SqliteDatabaseProvider : DbProviderBase, IDisposable
{
// 构造函数:传入连接字符串
public SqliteDatabaseProvider(string connectionString)
// 构造函数:传入已创建的连接实例
public SqliteDatabaseProvider(DbConnection connection)
// 获取表管理器(无需额外参数)
public ITableManager GetTableManager()
// 获取 SQL 执行器
public ISqlExecutor GetSqlExecutor()
// 释放资源
public void Dispose()
}
MongoDB 提供程序:
public class MongoDBProvider : DbProviderBase, IDisposable
{
// 构造函数:传入连接字符串和数据库名
public MongoDBProvider(string connectionString, string databaseName)
// 获取表管理器
public ITableManager GetTableManager()
// 获取 SQL 执行器(MongoDB 实现)
public ISqlExecutor GetSqlExecutor()
// 释放资源
public void Dispose()
}
设计优势:
- 简化 API:无需手动创建
SqlExecutor,内部自动管理 - 资源管理:实现
IDisposable,支持using语句自动释放资源 - 灵活选择:支持两种连接管理方式,满足不同场景需求
- 向后兼容:保留了接口方法
GetTableManager(DbConnection, ISqlExecutor) - MongoDB 集成:专门的 MongoDB 提供程序支持文档数据库特性
11.1.4 MySQL 提供程序
using JCode.ORMX.DataProviders.MySQL;
// 创建数据库提供程序(推荐方式:传入连接字符串)
using var provider = new MySqlDatabaseProvider("Server=localhost;Database=mydb;Uid=root;Pwd=password;");
// 获取表管理器(无需额外参数)
var tableManager = provider.GetTableManager();
// 获取表对象
var userTable = tableManager.Table<User>();
方式二:传入已创建的连接实例
using JCode.ORMX.DataProviders.MySQL;
using MySqlConnector;
// 创建数据库连接
using var connection = new MySqlConnection("Server=localhost;Database=mydb;Uid=root;Pwd=password;");
connection.Open();
// 创建数据库提供程序
using var provider = new MySqlDatabaseProvider(connection);
// 获取表管理器
var tableManager = provider.GetTableManager();
// 获取表对象
var userTable = tableManager.Table<User>();
MySQL 连接字符串:
// 基本连接
"Server=localhost;Database=mydb;Uid=root;Pwd=password;"
// 指定端口
"Server=localhost;Port=3306;Database=mydb;Uid=root;Pwd=password;"
// 带字符集
"Server=localhost;Database=mydb;Uid=root;Pwd=password;Charset=utf8mb4;"
11.1.5 PostgreSQL 提供程序
using JCode.ORMX.DataProviders.PostgreSQL;
// 创建数据库提供程序(推荐方式:传入连接字符串)
using var provider = new PgSqlDatabaseProvider("Host=localhost;Database=mydb;Username=postgres;Password=password;");
// 获取表管理器(无需额外参数)
var tableManager = provider.GetTableManager();
// 获取表对象
var userTable = tableManager.Table<User>();
方式二:传入已创建的连接实例
using JCode.ORMX.DataProviders.PostgreSQL;
using Npgsql;
// 创建数据库连接
using var connection = new NpgsqlConnection("Host=localhost;Database=mydb;Username=postgres;Password=password;");
connection.Open();
// 创建数据库提供程序
using var provider = new PgSqlDatabaseProvider(connection);
// 获取表管理器
var tableManager = provider.GetTableManager();
PostgreSQL 连接字符串:
// 基本连接
"Host=localhost;Database=mydb;Username=postgres;Password=password;"
// 指定端口
"Host=localhost;Port=5432;Database=mydb;Username=postgres;Password=password;"
// 带超时设置
"Host=localhost;Database=mydb;Username=postgres;Password=password;Timeout=30;"
11.1.6 SQL Server 提供程序
using JCode.ORMX.DataProviders.SqlServer;
// 创建数据库提供程序(推荐方式:传入连接字符串)
using var provider = new SqlServerDatabaseProvider("Server=localhost;Database=mydb;User Id=sa;Password=password;");
// 获取表管理器(无需额外参数)
var tableManager = provider.GetTableManager();
// 获取表对象
var userTable = tableManager.Table<User>();
方式二:传入已创建的连接实例
using JCode.ORMX.DataProviders.SqlServer;
using Microsoft.Data.SqlClient;
// 创建数据库连接
using var connection = new SqlConnection("Server=localhost;Database=mydb;User Id=sa;Password=password;");
connection.Open();
// 创建数据库提供程序
using var provider = new SqlServerDatabaseProvider(connection);
// 获取表管理器
var tableManager = provider.GetTableManager();
// 获取表对象
var userTable = tableManager.Table<User>();
SQL Server 连接字符串:
// 基本连接
"Server=localhost;Database=mydb;User Id=sa;Password=password;"
// 使用 Windows 身份验证
"Server=localhost;Database=mydb;Integrated Security=True;"
// 指定端口
"Server=localhost,1433;Database=mydb;User Id=sa;Password=password;"
11.2 SQL 执行器接口
11.2.1 ISqlExecutor 接口
ISqlExecutor 接口定义了 SQL 执行器的核心功能:
public interface ISqlExecutor : IDisposable
{
IDbProvider DatabaseProvider { get; }
IDbConnection Connection { get; }
List<T> ExecuteQuery<T>(string sql, params object[] parameters) where T : class, new();
T? ExecuteScalar<T>(string sql, params object[] parameters) where T : class, new();
int ExecuteNonQuery(string sql, params object[] parameters);
T? ExecuteSingleValue<T>(string sql, params object[] parameters);
IDataReader ExecuteReader(string sql, params object[] parameters);
T MapToEntity<T>(IDataReader reader) where T : class, new();
T MapToComplexEntity<T>(IDataReader reader) where T : class, new();
}
11.2.2 执行非查询命令
using JCode.ORMX.DataProviders.SQLite;
// 创建数据库提供程序
using var provider = new SqliteDatabaseProvider("Data Source=:memory:");
// 获取 SQL 执行器
var sqlExecutor = provider.GetSqlExecutor();
// 执行 INSERT 命令
var affectedRows = sqlExecutor.ExecuteNonQuery(
"INSERT INTO Users (Name, Email, Age) VALUES (@p0, @p1, @p2)",
"张三", "zhangsan@example.com", 25
);
// 执行 UPDATE 命令
var affectedRows = sqlExecutor.ExecuteNonQuery(
"UPDATE Users SET Age = @p0 WHERE Id = @p1",
26, 1
);
// 执行 DELETE 命令
var affectedRows = sqlExecutor.ExecuteNonQuery(
"DELETE FROM Users WHERE Id = @p0",
1
);
11.2.3 执行查询命令
using JCode.ORMX.DataProviders.SQLite;
// 创建数据库提供程序
using var provider = new SqliteDatabaseProvider("Data Source=:memory:");
// 获取 SQL 执行器
var sqlExecutor = provider.GetSqlExecutor();
// 执行查询命令并返回实体列表
var users = sqlExecutor.ExecuteQuery<User>(
"SELECT * FROM Users WHERE Age > @p0",
25
);
foreach (var user in users)
{
Console.WriteLine(<div class="latex">$"ID: {user.Id}, 姓名: {user.Name}, 年龄: {user.Age}");
}
11.2.4 执行标量查询
using JCode.ORMX.DataProviders.SQLite;
// 创建数据库提供程序
using var provider = new SqliteDatabaseProvider("Data Source=:memory:");
// 获取 SQL 执行器
var sqlExecutor = provider.GetSqlExecutor();
// 执行 COUNT 查询
var count = sqlExecutor.ExecuteScalar<int>(
"SELECT COUNT(*) FROM Users"
);
Console.WriteLine($</div>"总用户数:{count}");
// 执行 MAX 查询
var maxAge = sqlExecutor.ExecuteScalar<int>(
"SELECT MAX(Age) FROM Users"
);
Console.WriteLine(<div class="latex">$"最大年龄:{maxAge}");
// 执行 SUM 查询
var totalAmount = sqlExecutor.ExecuteScalar<decimal>(
"SELECT SUM(Amount) FROM Orders"
);
Console.WriteLine($</div>"订单总额:{totalAmount}");
11.3 表管理器接口
11.3.1 ITableManager 接口
ITableManager 接口定义了表管理器的核心功能:
public interface ITableManager
{
// 获取表名
string GetName(Type entityType);
// 检查表是否存在
bool Exists(Type entityType);
bool Exists(string tableName);
// 创建表
void Create(Type entityType);
void Create(Type entityType, string tableName);
// 更新表结构
void Update(Type entityType);
// 删除表
void Drop(Type entityType);
void Drop(string tableName);
// 获取表对象
ITable<T> Table<T>() where T : class, new();
}
11.3.2 获取表名
using JCode.ORMX.DataProviders.SQLite;
// 创建数据库提供程序(推荐方式)
using var provider = new SqliteDatabaseProvider("Data Source=:memory:");
var tableManager = provider.GetTableManager();
var tableName = tableManager.GetName(typeof(User));
Console.WriteLine(<div class="latex">$"表名:{tableName}");
11.3.3 检查表是否存在
using JCode.ORMX.DataProviders.SQLite;
// 创建数据库提供程序(推荐方式)
using var provider = new SqliteDatabaseProvider("Data Source=:memory:");
var tableManager = provider.GetTableManager();
// 检查实体类型对应的表是否存在
var exists = tableManager.Exists(typeof(User));
Console.WriteLine($</div>"User 表存在:{exists}");
// 检查表名是否存在
var exists = tableManager.Exists("User");
Console.WriteLine(<div class="latex">$"User 表存在:{exists}");
11.3.4 创建表
using JCode.ORMX.DataProviders.SQLite;
// 创建数据库提供程序(推荐方式)
using var provider = new SqliteDatabaseProvider("Data Source=:memory:");
// 获取表管理器
var tableManager = provider.GetTableManager();
// 创建表(使用实体类型的默认表名)
tableManager.Create(typeof(User));
// 创建表(指定表名)
tableManager.Create(typeof(User), "AppUsers");
Console.WriteLine("表创建成功");
11.3.5 更新表
using JCode.ORMX.DataProviders.SQLite;
// 创建数据库提供程序
using var provider = new SqliteDatabaseProvider("Data Source=:memory:");
// 获取表管理器
var tableManager = provider.GetTableManager();
// 更新表结构(添加新列、修改列类型等)
tableManager.Update(typeof(User));
Console.WriteLine("表更新成功");
11.3.6 删除表
using JCode.ORMX.DataProviders.SQLite;
// 创建数据库提供程序
using var provider = new SqliteDatabaseProvider("Data Source=:memory:");
// 获取表管理器
var tableManager = provider.GetTableManager();
// 删除实体类型对应的表
tableManager.Drop(typeof(User));
// 删除指定表名的表
tableManager.Drop("User");
Console.WriteLine("表删除成功");
11.4 SQL 调试功能
11.4.1 Debug 接口
IDebug<T> 接口提供了 SQL 调试功能:
public interface IDebug<T> : IBaseBuilder<T> where T : class, new()
{
}
11.4.2 使用 Debug 回调
using var userTable = tableManager.Table<User>();
// 设置 SQL 调试回调
userTable.Debug((sql, parameters) =>
{
Console.WriteLine($</div>"SQL: {sql}");
Console.WriteLine(<div class="latex">$"参数: {string.Join(", ", parameters)}");
})
.Where(u => u.Age > 25)
.GetList();
11.4.3 完整示例
using System;
using JCode.ORMX.Attributes;
using JCode.ORMX.DataProviders.SQLite;
using Microsoft.Data.Sqlite;
[Table(Name = "Users")]
public class User
{
[Column(IsPrimaryKey = true, IsAutoIncrement = true)]
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public int Age { get; set; }
}
class Program
{
static void Main(string[] args)
{
// 创建数据库提供程序(内部自动创建连接)
using var provider = new SqliteDatabaseProvider("Data Source=:memory:");
// 获取表管理器(无需额外参数)
var tableManager = provider.GetTableManager();
// 1. 获取数据库类型
Console.WriteLine("=== 数据库类型 ===");
Console.WriteLine($</div>"数据库类型:{provider.DriverType}");
// 2. 检查表是否存在
Console.WriteLine("\n=== 检查表 ===");
var exists = tableManager.Exists(typeof(User));
Console.WriteLine(<div class="latex">$"User 表存在:{exists}");
// 3. 创建表
Console.WriteLine("\n=== 创建表 ===");
if (!exists)
{
tableManager.Create(typeof(User));
Console.WriteLine("表创建成功");
}
// 4. 获取表对象
using var userTable = tableManager.Table<User>();
// 5. 插入数据
Console.WriteLine("\n=== 插入数据 ===");
var users = new List<User>
{
new User { Name = "张三", Email = "zhangsan@example.com", Age = 25 },
new User { Name = "李四", Email = "lisi@example.com", Age = 30 },
new User { Name = "王五", Email = "wangwu@example.com", Age = 28 }
};
userTable.InsertAll(users);
Console.WriteLine($</div>"插入了 {users.Count} 个用户");
// 6. 使用 Debug 回调查询数据
Console.WriteLine("\n=== 查询数据(带 Debug) ===");
var result = userTable
.Debug((sql, parameters) =>
{
Console.WriteLine(<div class="latex">$"SQL: {sql}");
Console.WriteLine($</div>"参数: [{string.Join(", ", parameters)}]");
})
.Where(u => u.Age > 25)
.GetList();
Console.WriteLine(<div class="latex">$"找到 {result.Count} 个年龄大于 25 的用户");
foreach (var user in result)
{
Console.WriteLine($</div>" - {user.Name}, 年龄: {user.Age}");
}
// 7. 使用 SQL 执行器执行自定义查询
Console.WriteLine("\n=== 自定义查询 ===");
var sqlExecutor = provider.GetSqlExecutor();
var customUsers = sqlExecutor.ExecuteQuery<User>(
"SELECT * FROM Users WHERE Name LIKE @p0",
"%张%"
);
Console.WriteLine(<div class="latex">$"找到 {customUsers.Count} 个姓名包含\"张\"的用户");
foreach (var user in customUsers)
{
Console.WriteLine($</div>" - {user.Name}, 邮箱: {user.Email}");
}
// 8. 执行标量查询
Console.WriteLine("\n=== 标量查询 ===");
var count = sqlExecutor.ExecuteScalar<int>("SELECT COUNT(*) FROM Users");
Console.WriteLine(<div class="latex">$"总用户数:{count}");
var maxAge = sqlExecutor.ExecuteScalar<int>("SELECT MAX(Age) FROM Users");
Console.WriteLine($</div>"最大年龄:{maxAge}");
}
}
11.5 资源释放
11.5.1 使用 using 语句(推荐)
using JCode.ORMX.DataProviders.SQLite;
// 推荐:使用 using 语句自动释放资源
using var provider = new SqliteDatabaseProvider("Data Source=:memory:");
var tableManager = provider.GetTableManager();
var userTable = tableManager.Table<User>();
// 使用表对象
// 自动释放资源(provider 释放时会自动释放内部的连接和 SQL 执行器)
说明:
SqliteDatabaseProvider实现了IDisposable接口- 使用
using语句可以自动释放资源 - 内部会自动释放数据库连接和 SQL 执行器
ITable<T>接口没有实现IDisposable,不需要使用using语句
11.5.2 手动释放资源
// 不推荐:手动管理资源
using JCode.ORMX.DataProviders.SQLite;
var provider = new SqliteDatabaseProvider("Data Source=:memory:");
try
{
var tableManager = provider.GetTableManager();
var userTable = tableManager.Table<User>();
// 使用表对象
}
finally
{
// 手动释放资源
provider.Dispose();
}
11.6 窗口函数
窗口函数是 ORMX 框架中的高级数据分析功能,详细内容请参考专门的窗口函数章节。
窗口函数功能特点:
- 支持 8 种常用窗口函数:RowNumber、Rank、DenseRank、NTile、Lag、Lead、FirstValue、LastValue
- 提供丰富的数据分析能力,如排名、分桶、趋势分析等
- 支持分区和排序,实现灵活的窗口定义
- 保持原始数据完整性,不会改变结果集的行数
使用示例:
// 行号函数示例
var result = userTable
.RowNumber("RowNum", u => u.Age) // 按 Age 排序,添加行号
.Column(u => new object[] { u.Id, u.Name, u.Age })
.GetList();
请查看窗口函数章节获取完整的使用指南和详细示例。
11.7 高级特性最佳实践
11.7.1 选择合适的数据库
| 场景 | 推荐数据库 | 原因 |
|---|---|---|
| 桌面应用 | SQLite | 轻量级,无需服务器 |
| 移动应用 | SQLite | 轻量级,跨平台 |
| Web 应用 | MySQL/PostgreSQL | 高并发,功能强大 |
| 企业应用 | SQL Server | 企业级支持,功能完整 |
| 微服务 | PostgreSQL | 功能强大,支持复杂查询 |
| 大数据应用 | MongoDB | 高性能,水平扩展能力强 |
| 内容管理系统 | MongoDB | 灵活的数据模型,易于扩展 |
| 实时分析 | MongoDB | 支持复杂查询和聚合操作 |
| IoT 应用 | MongoDB | 适合存储和查询时间序列数据 |
| 分布式应用 | Rides | 高性能,兼容 MySQL 协议 |
11.7.2 Redis 缓存集成
对于读密集型应用,建议集成 Redis 缓存以提高性能。详细配置和使用方法请参考Redis 缓存章节。
示例:
// 配置 Redis 缓存
var cacheOptions = new RedisCacheOptions
{
ConnectionString = "localhost:6379"
};
// 集成 Redis 缓存
using var provider = new SqliteDatabaseProvider("Data Source=test.db")
.WithRedisCache(cacheOptions);
// 自动缓存查询结果
var users = provider.GetTableManager().Table<User>()
.Where(u => u.Age > 25)
.GetList();
11.7.3 连接字符串管理
// 使用配置文件管理连接字符串
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build();
var connectionString = configuration.GetConnectionString("DefaultConnection");
11.7.3 错误处理
try
{
// 执行数据库操作
userTable.Insert(user);
}
catch (Exception ex)
{
// 记录错误日志
Console.WriteLine($"数据库操作失败:{ex.Message}");
// 根据错误类型处理
if (ex is SqlException sqlEx)
{
// 处理 SQL 特定错误
}
else
{
// 处理其他错误
}
}
11.7.4 性能优化
// 1. 使用批量操作
userTable.InsertAll(users);
// 2. 使用索引
sqlExecutor.ExecuteNonQuery("CREATE INDEX idx_users_age ON Users(Age)");
// 3. 使用分页
var users = userTable.Offset(0).Limit(10).GetList();
// 4. 只查询需要的列
var names = userTable.Select(u => u.Name).GetList();
11.8 总结
本章介绍了 ORMX 的高级特性,包括:
- 多数据库支持(SQLite、MySQL、PostgreSQL、SQL Server、MongoDB)
- 数据库提供程序接口
- SQL 执行器接口
- 表管理器接口
- SQL 调试功能
- 资源释放
- 窗口函数(详见专门章节)
- 高级特性最佳实践
核心接口回顾:
IDbProvider- 数据库提供程序接口ISqlExecutor- SQL 执行器接口ITableManager- 表管理器接口IDebug<T>- SQL 调试接口
支持的数据库:
- SQLite - 轻量级嵌入式数据库
- MySQL - 流行的开源关系数据库
- PostgreSQL - 功能强大的开源对象关系数据库
- SQL Server - 微软企业级关系数据库
- MongoDB - 面向文档的 NoSQL 数据库(支持事务和 ACID 特性)
- Rides - 高性能分布式数据库(兼容 MySQL 协议)
恭喜! 您已经完成了 ORMX 的全部教程学习。现在您应该能够:
- 使用 ORMX 进行基本的 CRUD 操作
- 构建复杂的查询
- 使用聚合函数进行数据统计
- 使用 Join 操作查询多个关联表
- 使用事务保证数据一致性
- 在多种数据库之间切换
- 使用 SQL 调试功能优化查询
- 使用窗口函数进行高级数据分析(详见窗口函数章节)
继续探索 ORMX 的强大功能,构建高效、可靠的数据访问层!
扩展思考
在实际项目中,如何根据业务需求选择合适的数据库类型?如何设计数据库连接池以提高性能?在微服务架构中,如何管理多个数据库连接?对于跨数据库的查询需求,如何实现数据同步和一致性?这些问题值得在深入使用 ORMX 后进一步思考。