如何用Fluent NHibernate将集合映射至泛型实体(遗留表场景)
嘿,我来帮你搞定这个Fluent NHibernate的映射问题!针对你说的通用DAT_DADO_EXTRA表关联泛型实体的需求,我整理了两种实用的实现方案,一起来看看:
解决方案:Fluent NHibernate映射通用ExtraData集合到泛型实体
首先先明确基础的实体结构,方便后续理解映射逻辑:
1. 定义通用ExtraData实体类
这个类对应你的DAT_DADO_EXTRA表,包含关联字段和自定义数据字段:
public class ExtraData { public virtual int Id { get; set; } public virtual string EntidadeRelacionada { get; set; } // 对应ENTIDADE_RELACIONADA字段,存储关联实体类型名 public virtual int IdEntidadeRelacionada { get; set; } // 对应ID_ENTIDADE_RELACIONADA字段,存储关联实体ID // 自定义数据字段示例,根据你的实际需求调整 public virtual string DataKey { get; set; } public virtual string DataValue { get; set; } }
2. 业务实体示例(比如Customer)
你的业务实体需要包含ExtraData的集合:
public class Customer { public virtual int Id { get; set; } // 其他业务字段... public virtual IList<ExtraData> ExtraData { get; set; } = new List<ExtraData>(); }
方式一:单个实体单独配置映射
如果你的系统里需要关联ExtraData的实体不多,可以直接在每个业务实体的映射类里单独配置:
public class CustomerMap : ClassMap<Customer> { public CustomerMap() { Id(x => x.Id); // 配置其他业务字段映射... // 核心:映射ExtraData集合 HasMany<ExtraData>(x => x.ExtraData) .Table("DAT_DADO_EXTRA") // 指定通用表名 .KeyColumn("ID_ENTIDADE_RELACIONADA") // 关联外键字段 .Where("ENTIDADE_RELACIONADA = 'Customer'") // 过滤当前实体类型的记录 .Cascade.AllDeleteOrphan(); // 根据业务需求设置级联规则,比如删除实体时同步删除关联的ExtraData } }
这里的关键是.Where()条件,它会让NHibernate只加载属于Customer类型的ExtraData记录。
方式二:泛型基类复用映射逻辑
如果有大量实体需要关联ExtraData,用泛型基类可以避免重复写相同的映射代码,提升复用性:
第一步:创建泛型实体基类
让所有需要ExtraData的业务实体继承这个基类:
public abstract class EntityWithExtraData<T> where T : EntityWithExtraData<T> { public virtual int Id { get; set; } public virtual IList<ExtraData> ExtraData { get; set; } = new List<ExtraData>(); } // 业务实体继承泛型基类 public class Customer : EntityWithExtraData<Customer> { // 自定义业务字段... }
第二步:创建泛型映射基类
封装通用的ExtraData集合映射逻辑:
public abstract class EntityWithExtraDataMap<T> : ClassMap<T> where T : EntityWithExtraData<T> { public EntityWithExtraDataMap() { Id(x => x.Id); // 自动获取当前实体的类型名,匹配ENTIDADE_RELACIONADA字段 var entityTypeName = typeof(T).Name; HasMany<ExtraData>(x => x.ExtraData) .Table("DAT_DADO_EXTRA") .KeyColumn("ID_ENTIDADE_RELACIONADA") .Where($"ENTIDADE_RELACIONADA = '{entityTypeName}'") .Cascade.AllDeleteOrphan(); } } // 业务实体的映射类继承泛型基类,只需配置特有字段 public class CustomerMap : EntityWithExtraDataMap<Customer> { public CustomerMap() : base() { // 配置Customer特有的业务字段... } }
额外注意事项
- 如果你的
ENTIDADE_RELACIONADA字段存储的是实体的完整命名空间+类名(比如YourProject.Entities.Customer),把typeof(T).Name改成typeof(T).FullName即可。 - 若需要双向关联,可以在
ExtraData类里添加virtual T RelatedEntity属性,然后在映射里加上.References(x => x.RelatedEntity)并启用.Inverse()。 - 测试时建议查看NHibernate生成的SQL,确认
Where条件是否正确生效,确保只加载对应实体的ExtraData记录。
内容的提问来源于stack exchange,提问作者Fabricio Casali
相关产品推荐
相关产品推荐

