zoukankan      html  css  js  c++  java
  • NHibernate之旅(6):探索NHibernate中的事务

    本节内容

    • 事务概述
    • 1.新建对象
      • 【测试成功提交】
      • 【测试失败回滚】
    • 2.删除对象
    • 3.更新对象
    • 4.保存更新对象
    • 结语

    上一篇我们介绍了NHibernate中的Insert, Update, Delete操作,这篇我们来看看NHibernate中的事务。你通过它可以提交或者回滚你的操作。

    事务概述

    1.NHibernate中的事务(Transactions)

    简单描述:要求ISession使用事务;做一些操作;提交或者回滚事务。

    写成代码就像这样:

    ITransaction tx = _session.BeginTransaction();
    //一些保存、更新、删除等操作
    tx.Commit();

    实际上在NHibernate使用事务要使用using强制资源清理和异常机制,一般像这样:

    using (ITransaction tx = _session.BeginTransaction())
    {
        try
        {
            //一些保存、更新、删除等操作
            tx.Commit();
        }
        catch (HibernateException)
        {
            tx.Rollback();
            throw;
        }
    }

    2.什么时候使用事务?

    回答是:在任何时候都要使用事务,即使是在读取、查询数据的时候,为什么呢?因为你不清楚数据库什么时候操作失败,如何恢复原来数据。而NHibernate中的事务(可以通过 tx.Rollback()方法),帮助我们完成这些事情。

    下面看看例子,我们修改上篇的Insert、Update、Delete操作:

    1.新建对象

    public int CreateCustomerTransaction(Customer customer)
    {
        using (ITransaction tx = _session.BeginTransaction())
        {
            try
            {
                int newId = (int)_session.Save(customer);
                _session.Flush();
                tx.Commit();
                return newId;
            }
            catch (HibernateException)
            {
                tx.Rollback();
                throw;
            }
        }
    }

    这篇以新建对象为例,分别从成功提交和失败回滚两个角度来测试这个方法。

    【测试成功提交】

    首先写一个测试用例,假设这个测试可以运行成功:

    [Test]
    public void CreateCustomerTransactionTest()
    {
        var customer = new Customer() { Firstname = "YJing", Lastname = "Lee" };
        int newIdentity = _transaction.CreateCustomerTransaction(customer);
        var testCustomer = _transaction.GetCustomerById(newIdentity);
        Assert.IsNotNull(testCustomer);
    }

    测试这个方法,使用TestDriven.NET集成的NCover(分析代码的覆盖率)查看代码运行覆盖率,在这个测试方法上右击选择“Test With”—“Coverage”,如下图所示:

    使用Coverage测试

    这时自动打开NCoverExplorer(查看代码覆盖率的分析结果),我们可以看到CreateCustomerTransaction方法运行覆盖情况,我们发现这个方法通过事务成功提交了操作并返回新的Id。分析结果效果图如下所示:

    成功提交代码覆盖率分析结果

    【测试失败回滚】

    我们在写一个失败回滚的测试,由于我认为设置了一个“将截断字符串或二进制数据”错误,这时必须在测试方法上指定测试预期的异常。

    [Test]
    [ExpectedException(typeof(NHibernate.HibernateException))]
    public void CreateCustomerThrowExceptionOnFailTest()
    {
        var customer = new Customer()
        {
            Firstname = "012345678901234567890123456789012345678901234567890123456789",
            Lastname = "YJingLee"
        };
        _transaction.CreateCustomerTransaction(customer);
    }

    同理按上面的步骤测试这个方法看看CreateCustomerTransaction方法运行情况,由于出现错误(这里是“将截断字符串或二进制数据”错误),所以系统抛出了HibernateException异常,此时系统发生回滚。分析结果效果图如下所示:

    失败回滚代码覆盖率分析结果

    2.删除对象

    我们修改上例中的删除对象的代码,如下所示:

    public void DeleteCustomerTransaction(Customer customer)
    {
        using (ITransaction tx = _session.BeginTransaction())
        {
            try
            {
                _session.Delete(customer);
                _session.Flush();
                tx.Commit();
            }
            catch (HibernateException)
            {
                tx.Rollback();
                throw;
            }
        }
    }

    3.更新对象

    我们修改上例中的更新对象的代码,如下所示:

    public void UpdateCustomerTransaction(Customer customer)
    {
        using (ITransaction tx = _session.BeginTransaction())
        {
            try
            {
                _session.Update(customer);
                _session.Flush();
                tx.Commit();
            }
            catch (HibernateException)
            {
                tx.Rollback();
                throw;
            }
        }
    }

    4.保存更新对象

    我们修改上例中的保存更新对象的代码,如下所示:

    public void SaveOrUpdateCustomersTransaction(IList<Customer> customers)
    {
        using (ITransaction tx = _session.BeginTransaction())
        {
            try
            {
                foreach (Customer c in customers)
                    _session.SaveOrUpdate(c);
                _session.Flush();
                tx.Commit();
            }
            catch (HibernateException)
            {
                tx.Rollback();
                throw;
            }
        }
    }

    好了,由于篇幅有限,上面三个方法在这里我就不测试了,大家可以参考创建对象测试的步骤来测试一下其他几个方法吧!

    结语

    感觉这节内容很少的样子,在NHibernate官方文档中对事务讲解的并不多,自己挖空心思也就挤了这么多东西。不过在这一节带领大家学会了测试工具TestDriven.NET的另一个功能就是怎么查看代码运行覆盖率,还是有一点收获的哦。下一节想继续深入事务话题一起讨论NHibernate中的并发控制,到现在还没有想好怎么写呢,希望大家对这个系列给出意见和建议。谢谢支持!

    本系列链接:NHibernate之旅系列文章导航

    NHibernate Q&A

    下次继续分享NHibernate!

  • 相关阅读:
    算法导论习题
    org.apache.subversion.javahl.ClientException: Item is not readable 解决办法
    nginx安装部署
    tomcat+jdk安装部署
    sql基本知识
    javascript权威指南学习笔记
    JAVA设计模式之---工厂模式
    Effective Java 之 --- 用私有构造器或者枚举类型强化Singleton属性
    接口中定义变量必须为public static final的原因
    对List中每个对象元素按时间顺序排序
  • 原文地址:https://www.cnblogs.com/lyj/p/1315032.html
Copyright © 2011-2022 走看看