NHibernate冷知识一则——自动修补空属性的缺省值

一、症状

老谭的角色之一是老中医,在电线杆子上贴小广告专治疑难杂症那种。

有一个问题袁俊杰已经反映两次了,就是在数据保存过程中NHibernate总是要更新Meter类的对象,而Meter类是从视图映射过来的,视图中定义了两个派生列,因此是不能更新的。问题是这个过程中从未对Meter对象的属性做过任何修改,而且所有引用Meter对象的关联关系中,cascade属性均置为none,update属性置为false(这个设置就属于病急乱投医了)。

问题到底出在哪儿呢?

二、原因

在项目的代码中找不到原因,老谭只得下狠手了:将各方的源代码找来,包括项目的,平台的,Spring.NET的,NHibernate的,将它们集中到一个Solution中,跟踪NHibernate的源代码。

结果发现,原因在于,NHibernate想要自动修补空属性的缺省值。

Meter类中有一个属性:

    public class Meter
    {
        ...
        /// <summary>))
        /// 是否为虚表
        /// </summary>
        [Property(Column = "real_flag")]
        public virtual bool IsVirtual { get; set; }
        ...
    }

其对应的数据表中的字段为real_flag:

注意real_flag这个字段是可空的,而Meter中IsVirtual属性为非空的。

在数据库中,当前访问记录的real_flag字段的值正是空值:


在这种情况下,NHibernate就做了一件“好事”:将空值null转换为bool型的缺省值false,将其赋给Meter的属性isVirtual。对Meter对象的这种修改,会回写到数据库中。我们称之为“自动修补空属性的缺省值”。

问题是,Meter对应的数据库对象是一个不可更新的视图,这最终导致NHibernate的异常。

总结一下,问题的根本原因在于Hibernate映射中属性的失配:表中的字段是可空的,而类中的属性是非空的。

三、解决

找到了问题的原因,解决起来就轻松了。下面任一方法都可以解决映射失配问题:

  1. 不修改数据库,而将类的属性设为可空的;
  2. 不修改程序代码,而将表的字段设为非空的;
  3. 在保存数据库记录时,确保给real_flag字段赋非空的值(注意:为该字段设置缺省值不能完全地解决该问题)。

四、启示

  • 开源代码有其潜在的优势。如果成熟水平相当,优先考虑开源代码。
  • 设法找到问题症结所在,通过调整使用方式解决问题。不宜绕开或放弃NHibernate,如利用SQL直接操纵数据;也不宜通过修改NHibernate的实现,构建自己专用的NHibernate版本来解决问题。
  • 做好架构设计。在架构中,隔离数据访问层、业务逻辑层和展现层的模型设计。特别是数据访问层中,Poco对象承担单一的数据交互职责,避免复杂的映射。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值