NHibernate 状态的概念 以及 小测试

在 NHibernate中有三种状态。

  • 临时态(Transient):用new创建的对象,它没有持久化,没有纳入Session中,随时可以被垃圾回收,处于此状态的对象叫临时对象。特点:数据库中没有与之对应的记录;
  • 持久态(Persistent):已经持久化,加入到了Session缓存中。通过NHibernate保存的对象或通过Get/Load等方法获取出的对象,其对象没有脱离Session的管理,处于此状态的对象叫持久对象;
  • 游离态(Detached):持久化对象脱离了Session的对象。如Session缓存被清空的对象。特点:已经持久化,但不在Session缓存中。处于此状态的对象叫游离对象;

 临时态(Transient)到持久态(Persistent)

先new一个对象,该对象的状态为Transient,然后调用Save()方法将该对象持久化到数据库中,该对象的状态变为Persistent。在未关闭Session前,修改该对象的属性,最后提交事务。

 1   /// <summary>
 2         /// 临时态-->持久态
 3         /// </summary>
 4         [Test]
 5         public void TransientToPersistentTest()
 6         {
 7             using (ISession session = this.sessionFactory.OpenSession())
 8             {
 9                 using (ITransaction tran = session.BeginTransaction())
10                 {
11                     //Transient
12                     var product = new Product
13                     {
14                         ID = Guid.NewGuid(),
15                         BuyPrice = 10M,
16                         Code = "ABC123",
17                         Name = "电脑",
18                         QuantityPerUnit = "20x1",
19                         SellPrice = 11M,
20                         Unit = ""
21                         
22                     };  
23 
24                     try
25                     {
26                         //Persistent
27                         session.Save(product);
28 
29                         //保存记录后修改数据,观察数据库中数据的变化
30                         product.SellPrice = 12M;
31 
32                         tran.Commit();
33                     }
34                     catch (Exception ex)
35                     {
36                         tran.Rollback();
37                         throw ex;
38                     }
39                 }
40             }
41         }

这时,我们心里便产生了一个疑问:把Product的SellPrice属性从“11M”修改为“12M”后,并没有调用Save()或者Update()的方法,为什么数据库中的数据会变呢?

  这是因为,当对象处于Persistent状态,并没有脱离Session管理时,其属性发生改变后,数据库相对应的记录会与之同步

持久态(Persistent)到游离态(Detached),再到持久态(Persistent)

 1  /// <summary>
 2         /// 持久态-->游离态-->持久态
 3         /// </summary>
 4         [Test]
 5         public void PersistentToTestDetached()
 6         {
 7             //Transient
 8             var product = new Product
 9             {
10                 ID = Guid.NewGuid(),
11                 BuyPrice = 10M,
12                 Code = "ABC123",
13                 Name = "电脑",
14                 QuantityPerUnit = "20x1",
15                 SellPrice = 11M,
16                 Unit = ""
17             };
18 
19             using (ISession session = this.sessionFactory.OpenSession())
20             {
21                 using (ITransaction tran = session.BeginTransaction())
22                 {                
23                     try
24                     {
25                         //Persistent
26                         session.Save(product);
27                         product.SellPrice = 12M;
28 
29                         tran.Commit();
30                     }
31                     catch (Exception ex)
32                     {
33                         tran.Rollback();
34                         throw ex;
35                     }
36                 }
37             }
38 
39             //Detached
40             product.SellPrice = 13M;
41 
42             using (ISession session = this.sessionFactory.OpenSession())
43             {
44                 using (ITransaction tran = session.BeginTransaction())
45                 {
46                     try
47                     {
48                         //Persistent
49                         session.Update(product);
50                         tran.Commit();
51                     }
52                     catch (Exception ex)
53                     {
54                         tran.Rollback();
55                         throw ex;
56                     }
57                 }
58             }
59         }

当对象处于游离态(Detached)时,修改其属性,是不会与数据库发生同步的。调用Update()方法后,对象则变回持久态(Persistent)。

Get方法得到持久态(Persistent)

 1         [Test]
 2         public void PersistentToTestDetached()
 3         {
 4             //Transient
 5             string  ID1 = Guid.NewGuid().ToString();
 6             var product = new Product
 7             {
 8                 ID = ID1,
 9                 BuyPrice = 10M,
10                 Code = "ABC123",
11                 Name = "电脑",
12                 QuantityPerUnit = "20x1",
13                 SellPrice = 11M,
14                 Unit = ""
15             };
16 
17             using (ISession session = this.sessionFactory.OpenSession())
18             {
19                 using (ITransaction tran = session.BeginTransaction())
20                 {
21                     try
22                     {
23                         //Persistent
24                         session.Save(product);
25                         product.SellPrice = 12M;
26 
27                         tran.Commit();
28                     }
29                     catch (Exception ex)
30                     {
31                         tran.Rollback();
32                         throw ex;
33                     }
34                 }
35             }
36 
37             //Detached
38            
39 
40             using (ISession session = this.sessionFactory.OpenSession())
41             {
42                 using (ITransaction tran = session.BeginTransaction())
43                 {
44                     try
45                     {
46                         //Persistent
47                         product=session.Get<Product>(ID1);//Get可与Load互换
48                         product.SellPrice = 18M;
49                         tran.Commit();
50                     }
51                     catch (Exception ex)
52                     {
53                         tran.Rollback();
54                         throw ex;
55                     }
56                 }
57             }
58         }

其中ID1为数据库中已存在的一条数据的主键值。在得到持久化对象后,我们便可以更改数据库的值。

 Get和Load()方法的区别

Load:

  • Load方法可以对查询进行优化。
  • Load方法实际得到一proxy对象,并不立即查询数据库。当访问对象的属性的时候才查询数据库。在NHibernate里称为Lazy Loding(延迟加载)。
  • Load方法得到的对象,如果对象不存在,在访问对象的属性时将抛出异常。
  • 当需要得到实体对象,但是不需要访问对象属性的时候,宜使用Load方法。比如Delete方法:

   调用Load()方法查询数据库中不存在的对象,返回值不为空;当调用Load()方法时,不立刻产生SQL语句,查看其属性后才产生SQL语句,并且查看数据库中不存在对象的属性时会抛出异常。原因是调用Load()方法会返回一个“代理类”,这是NHibernate的一个重要的特性——延迟加载。

 延迟加载(lazy load)也叫“懒加载”,是NHibernate关联关系对象默认的加载方式,延迟加载机制是为了避免一些无谓的性能开销而提出来的,所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作。可以简单理解为,只有在使用的时候,才会发出SQL语句进行查询。 延迟加载的有效期是在Session打开的情况下,当Session关闭后,会报异常。NHibernate的代理对象是由第三方组件“Antlr3.Runtime”提供的。

Get:

  • Get方法立即查询数据库,如果对象不存在,返回null。
  • 调用Get()方法后,数据库中不存在的对象返回值为null,并且一但调用Get()方法,就会生成SQL语句。

Update()方法

先手动打造new一个数据库中存在的游离态(Detached)对象,然后直接调用Update()方法将对象的状态设置为持久态(Persistent)。

 1    [Test]
 2         public void UpdateTest()
 3         {
 4             Guid id = Guid.NewGuid();
 5 
 6             using (ISession session = this.sessionFactory.OpenSession())
 7             {             
 8                 using (ITransaction tran = session.BeginTransaction())
 9                 {
10                     //Transient
11                     var product = new Product
12                     {
13                         ID = id,
14                         BuyPrice = 10M,
15                         Code = "ABC123",
16                         Name = "电脑",
17                         QuantityPerUnit = "20x1",
18                         SellPrice = 11M,
19                         Unit = ""
20 
21                     };
22 
23                     try
24                     {
25                         //Persistent
26                         session.Save(product);
27                         tran.Commit();
28                     }
29                     catch (Exception ex)
30                     {
31                         tran.Rollback();
32                         throw ex;
33                     }
34                 }
35             }
36 
37             using (ISession session = this.sessionFactory.OpenSession())
38             {
39                 using (ITransaction tran = session.BeginTransaction())
40                 {
41                     //Detached
42                     var product = new Product
43                     {
44                         ID = id,
45                         Code = "ABC456",
46                     };
47 
48                     try
49                     {
50                         //Persistent
51                         session.Update(product);
52 
53                         tran.Commit();
54                     }
55                     catch (Exception ex)
56                     {
57                         tran.Rollback();
58                         throw ex;
59                     }
60                 }
61             }
62         }

有的朋友就会问,为什么new的时候也能得到游离态(Detached)对象?因为判断是否为游离态(Detached)对象,是根据数据库中是否存在与之对应的记录定夺的。

 Delete()方法

先得到一个持久态(Persistent)对象,然后调用Delete()方法删除该对象,这时该对象变回临时态(Transient)

 1  [Test]
 2         public void DeleteTest()
 3         {
 4             using (ISession session = this.sessionFactory.OpenSession())
 5             {
 6                 using (ITransaction tran = session.BeginTransaction())
 7                 {
 8                     //Transient
 9                     var product = new Product
10                     {
11                         ID = Guid.NewGuid(),
12                         BuyPrice = 10M,
13                         Code = "ABC123",
14                         Name = "电脑",
15                         QuantityPerUnit = "20x1",
16                         SellPrice = 11M,
17                         Unit = ""
18 
19                     };
20 
21                     try
22                     {
23                         //Persistent
24                         session.Save(product);
25 
26                         //Transient
27                         session.Delete(product);
28 
29                         tran.Commit();
30                     }
31                     catch (Exception ex)
32                     {
33                         tran.Rollback();
34                         throw ex;
35                     }
36                 }
37             }
38         }

学习于      http://www.cnblogs.com/GoodHelper/archive/2011/02/17/nhibernate_04.html

原文地址:https://www.cnblogs.com/cwmizlp/p/9208291.html