NHibernate从入门到精通系列(5)——持久对象的生命周期(下)

 内容摘要

    持久化类

    持久化生命周期中的回调

    合法性验证回调

 

    一、持久化类(Persistent Classes)

      1.1 什么是持久化类

  回答这个问题之前先回答什么是持久化。所谓的持久化就是把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘)。然而持久化类就是持久化数据的载体,在应用程序中,用来实现业务问题实体的(如,在电子商务应用程序中的Customer和Order) 类就是持久化类。不能认为所有的持久化类的实例都是持久的状态——一个实例的状态也可能 是瞬时的或脱管的。 如果这些持久化类遵循一些简单的规则,NHibernate能够工作得更好,这些规则也被称作 简单传统CLR对象(POCO:Plain Old CLR Object)编程模型。

  之前用到的“Product”类,就是持久化类

Product 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Domain
{
    /// <summary>
    /// 商品
    /// </summary>
    public class Product
    {
        /// <summary>
        /// ID
        /// </summary>
        public virtual Guid ID { get; set; }

        /// <summary>
        /// 编号
        /// </summary>
        public virtual string Code { get; set; }

        /// <summary>
        /// 名称
        /// </summary>
        public virtual string Name { get; set; }

        /// <summary>
        /// 规格
        /// </summary>
        public virtual string QuantityPerUnit { get; set; }

        /// <summary>
        /// 单位
        /// </summary>
        public virtual string Unit { get; set; }

        /// <summary>
        /// 售价
        /// </summary>
        public virtual decimal SellPrice { get; set; }

        /// <summary>
        /// 进价
        /// </summary>
        public virtual decimal BuyPrice { get; set; }

        /// <summary>
        /// 备注
        /// </summary>
        public virtual string Remark { get; set; }
    }
}

然而持久化类须满足一定的规则。

 

      1.2持久化类的规则

  • 实现一个默认的(即无参数的)构造方法(constructor)
  • 提供一个标识属性(identifier property)(可选)
  • 使用非密封(non-sealed)类以及虚方法(virtual methods) (可选)

 

  二、持久化生命周期中的回调

  2.1 ILifecycle接口介绍

  持久化类可以实现ILifecycle接口,它可以提供一些用于回调的方法, 可以让持久化对象在Save或Load之后,或者在Delete或Update之前进行必要的初始化与清除步骤。

  让我们看一下ILifecycle接口 


ILifecycle 

    public interface ILifecycle
    {
        LifecycleVeto OnDelete(ISession s);
        void OnLoad(ISession s, object id);
        LifecycleVeto OnSave(ISession s);
        LifecycleVeto OnUpdate(ISession s);
    }

其中ILifecycle接口的方法如下:

(1)

OnSave - 在对象即将被save或者insert的时候回调

(2)

OnUpdate - 在对象即将被update的时候回调(也就是对象被传递给ISession.Update()的时候)

(3)

OnDelete - 在对象即将被delete(删除)的时候回调

(4)

OnLoad - 在对象刚刚被load(装载)后的时候回调

 

  如果OnSave()OnUpdate() 或者 OnDelete()返回LifecycleVeto.Veto,那么操作就被悄悄地取消了。 如果其中抛出了CallbackException异常,操作被取消,这个异常会被继续传递给应用程序。

 

  2.2 ILifecycle的demo

  实体:  

Product 

/// <summary>
    /// 商品
    /// </summary>
    public class Product : ILifecycle
    {
        /// <summary>
        /// ID
        /// </summary>
        public virtual Guid ID { get; set; }

        /// <summary>
        /// 编号
        /// </summary>
        public virtual string Code { get; set; }

        /// <summary>
        /// 名称
        /// </summary>
        public virtual string Name { get; set; }

        /// <summary>
        /// 规格
        /// </summary>
        public virtual string QuantityPerUnit { get; set; }

        /// <summary>
        /// 单位
        /// </summary>
        public virtual string Unit { get; set; }

        /// <summary>
        /// 售价
        /// </summary>
        public virtual decimal SellPrice { get; set; }

        /// <summary>
        /// 进价
        /// </summary>
        public virtual decimal BuyPrice { get; set; }

        /// <summary>
        /// 备注
        /// </summary>
        public virtual string Remark { get; set; }


        public virtual LifecycleVeto OnDelete(NHibernate.ISession s)
        {
            Console.WriteLine("您调用了Delete()方法!");
            return LifecycleVeto.NoVeto;
        }

        public virtual void OnLoad(NHibernate.ISession s, object id)
        {
            Console.WriteLine("您调用了Load()方法!");
        }

        public virtual LifecycleVeto OnSave(NHibernate.ISession s)
        {
            Console.WriteLine("您调用了Save()方法!");
            return LifecycleVeto.NoVeto;
        }

        public virtual LifecycleVeto OnUpdate(NHibernate.ISession s)
        {
            Console.WriteLine("您调用了Update()方法!");
            return LifecycleVeto.NoVeto;
        }
    }

单元测试:


LifecycleTest 

[TestFixture]
    public class LifecycleTest
    {
        private ISessionFactory sessionFactory;

        private static readonly Guid s_id = Guid.NewGuid();

        [SetUp]
        public void Init()
        {
            var cfg = new NHibernate.Cfg.Configuration().Configure("Config/hibernate.cfg.xml");
            sessionFactory = cfg.BuildSessionFactory();
        }

        [Test]
        public void SaveTest()
        {
            using (ISession session = this.sessionFactory.OpenSession())
            {
                using (ITransaction tran = session.BeginTransaction())
                {
                    try
                    {
                        var product = new Product
                        {
                            ID = s_id,
                            BuyPrice = 10M,
                            Code = "ABC123",
                            Name = "电脑",
                            QuantityPerUnit = "20x1",
                            SellPrice = 11M,
                            Unit = "台"
                        };

                        session.Save(product);

                        tran.Commit();
                    }
                    catch (Exception ex)
                    {
                        tran.Rollback();
                        throw ex;
                    }
                }
            }
        }

        [Test]
        public void UpdateTest()
        {
            using (ISession session = this.sessionFactory.OpenSession())
            {
                using (ITransaction tran = session.BeginTransaction())
                {
                    try
                    {
                        var product = session.Load<Product>(s_id);

                        product.BuyPrice = 12M;
                        session.Update(product);

                        tran.Commit();
                    }
                    catch (Exception ex)
                    {
                        tran.Rollback();
                        throw ex;
                    }
                }
            }
        }

        [Test]
        public void DeleteTest()
        {
            using (ISession session = this.sessionFactory.OpenSession())
            {
                using (ITransaction tran = session.BeginTransaction())
                {
                    try
                    {
                        var product = session.Load<Product>(s_id);

                        session.Delete(product);

                        tran.Commit();
                    }
                    catch (Exception ex)
                    {
                        tran.Rollback();
                        throw ex;
                    }
                }
            }
        }
    }

 运行SaveTest()方法的效果,如图2.2.1所示。

图2.2.1

 

  运行UpdateTest()方法的效果,如图2.2.2所示。奇怪的是OnUpdate()回调没有工作,这是因为在NHibernate 1.x 以后的版本,ILifecycle接口已经不建议使用了。

图2.2.2

 

  运行DeleteTest()方法的效果,如图2.2.3所示。

图2.2.3

 

  三、合法性验证回调

  合法性验证(IValidatable)回调是在持久化类在保存其持久化状态前进行合法性检查的接口。


public interface IValidatable
{
        void Validate();
}

如果发现对象违反了某条规则,应该抛出一个 ValidationFailure 异常。在 Validatable 实例的 Validate() 方法内部不应该改变它的状态。

ILifecycle接口的回调方法不同,Validate()可能在任何时间被调用。应用程序不应该把Validate()调用和商业功能联系起来。

 

  实现代码如下:

代码 

public class Product : IValidatable
    {

        ....


        /// <summary>
        /// 进价
        /// </summary>
        public virtual decimal BuyPrice { get; set; }


        public virtual void Validate()
        {
            if (this.BuyPrice >= 12M)
            {
                throw new ValidationFailure("进货价格太高,无法受理!");
            }
        }
    }

运行效果如图3.1所示

图3.1

 

  总结:目前NHibernate 3.0版本中不建议使用ILifecycle和IValidatable接口。因为这样NHibernate框架就会对持久化类产生侵入性。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值