如何在NHibernate中映射计算得出的List类型属性?
问题描述
我的模型包含以下属性:
public virtual DateTime LastSessionDate { get; set; } public virtual List<double> Values { get; set; }
其中LastSessionDate通过<property>的formula属性映射自定义SQL查询,运行正常:
<property name="LastSessionDate" formula="(select ...)" />
但Values属性需要从其他表通过自定义SQL查询获取,尝试多种<bag>和<subselect>组合均未成功。使用以下配置时抛出NHibernate.MappingException异常:persistent class not known: System.Collections.Generic.List1[[System.Double]]`
<many-to-one name="Values" access="readonly"> <formula>(select ...)</formula> </many-to-one>
解决思路
1. 纠正映射类型:用值类型集合映射而非many-to-one
many-to-one用于映射单个实体关联,而List<double>是值类型集合,需要用<bag>或<list>(对应.NET的ICollection<T>或IList<T>)来映射,搭配<element>指定值类型。
2. 使用subselect定义自定义查询
通过subselect属性直接指定获取集合数据的SQL查询,需确保查询返回两列:
- 关联当前实体的外键列(需与当前实体主键匹配)
- 存储double值的列
示例配置:
<!-- 假设当前实体主键为Id,查询返回entity_id(关联主键)和value(double值) --> <bag name="Values" access="readonly" subselect="select entity_id, value from other_table where [你的过滤条件]" lazy="false"> <key column="entity_id" /> <!-- 关联当前实体的主键 --> <element type="Double" column="value" /> <!-- 指定集合元素类型和对应列 --> </bag>
3. 替代方案:使用内联表定义
如果需要更灵活的SQL,也可以直接在table属性中嵌套子查询:
<bag name="Values" access="readonly" table="(select entity_id, value from other_table where [你的过滤条件])" lazy="false"> <key column="entity_id" /> <element type="Double" column="value" /> </bag>
注意事项
- 确保子查询返回的外键列(如
entity_id)与当前实体的主键列完全匹配,NHibernate会自动将当前实体的主键值代入查询,过滤出对应的数据 - 如果不需要懒加载,设置
lazy="false"可确保集合在加载实体时一并获取 - 若需保持List的顺序,可改用
<list>并指定<index>列,但需确保子查询返回顺序相关的列(若自定义SQL有排序逻辑,<bag>也能保留结果顺序,但NHibernate不保证<bag>的顺序稳定性)
内容的提问来源于stack exchange,提问作者jgayer
相关产品推荐
相关产品推荐

