如何无需重建SessionFactory,动态增删改NHibernate类映射与实体?
解决方案建议
1. 基于动态模型(Dynamic Model)的无实体映射方案
既然你需要动态创建表和修改架构,完全可以抛弃静态实体类,改用NHibernate的动态模型(Dynamic Map)特性,直接用IDictionary<string, object>作为"实体"操作,不需要预先定义映射文件或实体类:
- 创建表/修改架构:直接用
SchemaExport或SchemaUpdate执行DDL语句,不需要修改Configuration或SessionFactory - CRUD操作:通过
ISession.CreateCriteria(typeof(object), "entityName")指定表名(实体名),结合ICriteria进行查询,完全兼容你现有的ICriteria依赖 - 内存优势:不需要维护大量实体映射,单个
SessionFactory即可处理所有动态表,内存占用极低
示例代码:
// 动态生成并执行建表DDL var ddl = "CREATE TABLE DynamicTable_123 (Id INT PRIMARY KEY, Value VARCHAR(255))"; new SchemaExport(config).Execute(false, true, false, session.Connection, null); // 使用ICriteria查询动态表 using (var session = sessionFactory.OpenSession()) { var criteria = session.CreateCriteria("DynamicTable_123") .Add(Restrictions.Eq("Id", 1)); var result = criteria.UniqueResult<IDictionary<string, object>>(); }
2. 自定义元数据提供者扩展SessionFactory
NHibernate允许自定义IMetadataProvider和IMetadataImplementor,你可以通过以下方式扩展现有SessionFactory的元数据:
- 继承
DefaultMetadataProvider,重写获取映射的方法,动态加载最新的表结构元数据 - 利用NHibernate内部API(注意:非官方公开API,版本升级需适配),在运行时更新
SessionFactory的元数据缓存 - 所有操作需保证线程安全,复用原有
SessionFactory实例,避免重建
此方案可满足你"单SessionFactory"的核心需求,但需注意版本兼容性。
3. 架构变更与SessionFactory解耦
将表创建/架构修改操作与SessionFactory完全解耦:
- 维护一个基础
SessionFactory,仅包含通用工具类或空映射 - 动态创建表/修改架构时,直接使用
SchemaUpdate或原生SQL执行DDL,不修改SessionFactory的配置 - 操作动态表时,通过
ISession.CreateSQLQuery或ICriteria结合动态实体名(表名)进行操作,无需将新表映射添加到Configuration中
这种方式完全避免了重建SessionFactory的开销,同时兼容ICriteria、ISession和ITransaction特性。
4. 分批次SessionFactory策略(折中方案)
如果必须使用实体映射,可以采用分批次维护SessionFactory:
- 将数百万张表按逻辑分组(比如业务模块、时间区间),每个组对应一个
SessionFactory - 新增表时,将其添加到对应组的
SessionFactory配置中,仅重建该组的SessionFactory,而非全部 - 相比单表单
SessionFactory,内存开销可降低数个数量级,同时保证性能
关键注意事项
- 线程安全:所有动态操作必须保证线程安全,修改元数据或执行DDL时需加锁或用并发控制机制
- 缓存处理:使用二级缓存时,动态修改架构后需清理对应表的缓存,避免脏数据
- 事务管理:动态DDL操作需注意事务隔离级别,避免并发冲突
内容的提问来源于stack exchange,提问作者Ember Freak
相关产品推荐
相关产品推荐

