NHibernate陷阱:many-to-one关联中的ghost对象
问题
NHibernate的many-to-one关联是支持多态的(理应),然而一不留神,代码就掉进了陷阱。考虑这个类图,OrderLine 有一个Product属性,同时,Product有两个子类。
1 | 这个关联的映射: |
1 | |
1 | < many-to-one Name="Product" class="Product" column="ProductId" /> |
1 | |
接下来,要为 Food 的订单行执行一点特别的业务逻辑:
1 2 3 4 | OrderLine line = ...; if (line.Product is Food) { // 永远不会执行到这里 |
1 | } |
1 | |
即使 line 的 Product 是 Food,这个判断也不会成立,针对Food的业务逻辑永远不会执行。
原因
造成这个问题的原因是 NHibernate 默认使用代理对象实现 many-to-one 的延迟加载,程序运行后,类结构实际上是这样的(紫色的类是nhibernate生成的代理类,实际的代理类名称与图中不同):
line对象构造出来以后,他的 Product 属性没有初始化,实际上,它是 ProductProxy 的实例(ghost对象),而 ProductProxy 和 Food 并无转换关系,表达式 (line.Product is Food) 永远为 false。
解决
为了避免 ghost 对象的问题,需要对关联的延迟加载稍稍做一点配置。如果不需要延迟加载,可以禁用:
1 | < many-to-one Name="Product" class="Product" column="ProductId" lazy="false"/> |
或者,如果仍然需要延迟加载,可以使用 no-proxy 选项,告诉 NHibernate 仍然延迟加载Product关联,但是不要使用代理对象。
1 | < many-to-one Name="Product" class="Product" column="ProductId" lazy="no-proxy" /> |
分类:
NHibernate
标签:
nhibernate
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决