01-03-03【Nhibernate (版本3.3.1.4000) 出入江湖】cascade的测试

相关文章:

http://www.cnblogs.com/amboyna/archive/2008/02/18/1072260.html
注意上面是hibernate,不是Nhibernate,这解释是否用于Nhibernate,自己验证。

cascade的取值范围:
all : 所有情况下均进行关联操作。 
none:所有情况下均不进行关联操作。这是默认值。 
save-update:在执行save/update/saveOrUpdate时进行关联操作。 
delete:在执行delete时进行关联操作。

all的意思是save-update
+ delete 
all-delete-orphan
的意思是当对象图中产生孤儿节点时,在数据库中删除该节点 
all比较好理解,举个例子说一下all-delete-orphan: 
Category与Item是一对多的关系,也就是说Category类中有个Set类型的变量items. 
举个例子,现items中存两个Item,
item1,item2,如果定义关系为all-delete-orphan 
当items中删除掉一个item(比如用remove()方法删除item1),那么被删除的Item类实例 
将变成孤儿节点,当执行category.update(),或session.flush()时 
hibernate同步缓存和数据库,会把数据库中item1对应的记录删掉



说在前头:
关于是否要级联操作,In my Opinion,还要看实际情况,
1.看关系是否属于识别性(如:鸟与翅膀的关系)与非识别性(独立个体:老师与学生的关系),
2.看业务需求。
3.看你老大的。。你懂的

-----------------------------------一言归正传:

Customer和Order的关系是1对多,即是:1个Customer有多个Order

测试一:cascade="all"

Customer.hbm.xml:


  <class name="Model.Customer, Model"
discriminator-value="0">
。。。。
<set name="Orders" table="Order" generic="true"
inverse="true" cascade="all">
<key column="CustomerId" foreign-key="FK_CustomerOrders"/>
<one-to-many class="Model.Order,Model"/>
</set>
</class>
</hibernate-mapping>

测试代码清单一:


 1         /// <summary>
2 /// 测试联级删除
3 /// Customer和Order配置了cascade="all",
4 /// 但是先在内存中解除从属关系,使之成为orphan (孤儿)
5 /// </summary>
6 [TestMethod]
7 public void TestDeleteCustomer_Cascade_All_RemoveOrderInMemery()
8 {
9 CustomerService customerService = new CustomerService();
10 OrderService orderService = new OrderService();
11
12 Customer customer = new Customer()
13 {
14 FirstName = "firstName_test1",
15 LastName = "Cascade",
16 Age = 10
17 };
18
19 Order order1 = new Order()
20 {
21 OrderDate = DateTime.Now,
22 Customer = customer
23 };
24
25 Order order2 = new Order()
26 {
27 OrderDate = DateTime.Now,
28 Customer = customer
29 };
30
31 //如果不加这一句:只添加Customer到数据,Order没有被添加到数据库
32 customer.Orders.Add(order1);
33 customer.Orders.Add(order2);
34
35 //添加后customer.CustomerId被自动赋值
36 customerService.Add(customer);
37 Assert.IsNotNull(customerService.Find(customer.CustomerId));
38 Assert.IsNotNull(orderService.Find(order1.OrderId));
39 Assert.IsNotNull(orderService.Find(order2.OrderId));
40
41 //先在内存中解除从属关系,使之成为orphan (孤儿)
42 //customer.Orders.Remove(order2);
43
44 customerService.Delete(customer);
45 Assert.IsNotNull(customerService.Find(customer.CustomerId));
46 Assert.IsNotNull(orderService.Find(order1.OrderId));
47 Assert.IsNotNull(orderService.Find(order2.OrderId));
48 }

以上用测试代码:

customer.Orders.Remove(order2); //先在内存中解除从属关系,使之成为orphan (孤儿)


使得

order2变成孤儿后,删除Customer时会引发异常如下异常,说明数据库不允许删除。

上面的单元测试没有通过,而是抛出异常:
Bug跟踪调试,会发现,删除失败的原因是,发生了如下异常:

{"DELETE 语句与 REFERENCE 约束\"FK_CustomerOrders\"冲突。该冲突发生于数据库\"NHibernateSampleAutoCreateTable\",表\"dbo.Order\", column ‘CustomerId‘。\r\n语句已终止。"}

补充:如果注释掉

customer.Orders.Remove(order2); //先在内存中解除从属关系,使之成为orphan (孤儿)

也即,不产生孤儿,级联删除是成功的。即使是MS SQL Server(其他数据库没测试过)级联操作设置为:"不执行操作",如下图:

测试二:cascade="all-delete-orphan"

Customer.hbm.xml:


  <class name="Model.Customer, Model"
discriminator-value="0">
<!--unsaved-value="0" 主键表中不需要定义,而是需要在子表中定义-->
<id name="CustomerId"
column="CustomerId"
type="int"
unsaved-value="0">
<generator class="native" />
<!-- unsaved-value used to be null and generator was increment in h2.0.3 -->
</id>

<!--version标签必须放在Id后面,否则出错-->
<version name="Version"/>

<property name="FirstName" >
<column name="Firstname" length="50" not-null="true"/>
</property>

<property name="LastName" type="String">
<column name="Lastname"/>
</property>

<property name="Age" type="int">
<column name="Age"/>
</property>

<set name="Orders" table="Order" generic="true"
inverse="true" cascade="all-delete-orphan">
<key column="CustomerId" foreign-key="FK_CustomerOrders"/>
<one-to-many class="Model.Order,Model"/>
</set>
</class>

再执行下面测试代码清单二:


 1         /// <summary>
2 /// 测试联级删除
3 /// Customer和Order配置了cascade="all-delete-orphan",
4 /// 但是先在内存中解除从属关系,使之成为orphan (孤儿)
5 /// </summary>
6 [TestMethod]
7 public void TestDeleteCustomer_Cascade_all_delete_orphan_RemoveOrderInMemery()
8 {
9 CustomerService customerService = new CustomerService();
10 OrderService orderService = new OrderService();
11
12 Customer customer = new Customer()
13 {
14 FirstName = "firstName_test1",
15 LastName = "Cascade",
16 Age = 10
17 };
18
19 Order order1 = new Order()
20 {
21 OrderDate = DateTime.Now,
22 Customer = customer
23 };
24
25 Order order2 = new Order()
26 {
27 OrderDate = DateTime.Now,
28 Customer = customer
29 };
30
31 //如果不加这一句:只添加Customer到数据,Order没有被添加到数据库
32 customer.Orders.Add(order1);
33 customer.Orders.Add(order2);
34
35 //添加后customer.CustomerId被自动赋值
36 customerService.Add(customer);
37 Assert.IsNotNull(customerService.Find(customer.CustomerId));
38 Assert.IsNotNull(orderService.Find(order1.OrderId));
39 Assert.IsNotNull(orderService.Find(order2.OrderId));
40
41 //先在内存中解除从属关系,使之成为orphan (孤儿)
42 //customer.Orders.Remove(order2);
43
44 //customerService.Delete(customer);
45 Assert.IsNull(customerService.Find(customer.CustomerId));
46 Assert.IsNull(orderService.Find(order1.OrderId));
47 Assert.IsNull(orderService.Find(order2.OrderId));
48 }

看图解:

结论:

                    cascade="all"                     cascade="all-delete-orphan"

不产生孤儿          删父时联级删子  
                     
        删父时联级删子

产生孤儿             抛异常
                     
                   
 删父时联级删子

时间: 2024-10-12 07:37:22

01-03-03【Nhibernate (版本3.3.1.4000) 出入江湖】cascade的测试的相关文章

01-08-03【Nhibernate (版本3.3.1.4000) 出入江湖】二级缓存:NHibernate自带的HashtableProvider之缓存管理

http://www.cnblogs.com/lyj/archive/2008/11/28/1343418.html 管理NHibernate二级缓存 NHibernate二级缓存由ISessionFactory创建并由ISessionFactory自行维护.我们使用NHibernate操作数据时,ISessionFactory能够自动同步缓存,保证缓存的有效性.但是当我们批量操作数据时,往往NHibernate不能维护缓存持久有效.ISessionFactory提供了可编程方式的缓存管理方法.

01-06-01【Nhibernate (版本3.3.1.4000) 出入江湖】事务

Nhibernate事务的使用: public void Add(Customer customer) { ISession session = _sessionManager.GetSession(); ITransaction transaction = session.BeginTransaction(); try { session.Save(customer); session.Flush();//清除一级缓存 transaction.Commit(); } catch (Except

01-08-01【Nhibernate (版本3.3.1.4000) 出入江湖】NHibernate中的三种状态

以下属于不明来源资料: 引入 在程序运行过程中使用对象的方式对数据库进行操作,这必然会产生一系列的持久化类的实例对象.这些对象可能是刚刚创建并准备存储的,也可能是从数据库中查询的,为了区分这些对象,根据对象和当前会话的关联状态,我们可以把对象分为三种: 瞬时对象:对象刚刚建立.该对象在数据库中没有记录,也不在ISession缓存中.如果该对象是自动生成主键,则该对象的对象标识符为空. 持久化对象:对象已经通过NHibernate进行了持久化,数据库中已经存在对应的记录.如果该对象是自动生成主键,

01-08-01【Nhibernate (版本3.3.1.4000) 出入江湖】NHibernate中的一级缓存

缓存的范围? 1.事务范围 事务范围的缓存只能被当前事务访问,每个事务都有各自的缓存,缓存内的数据通常采用相互关联的对象形式.缓存的生命周期依赖于事务的生命周期,只有当事务结束时,缓存的生命周期才会结束.事务范围的缓存使用内存作为存储介质,一级缓存就属于事务范围. 2.应用范围 应用程序的缓存可以被应用范围内的所有事务共享访问.缓存的生命周期依赖于应用的生命周期,只有当应用结束时,缓存的生命周期才会结束.应用范围的缓存可以使用内存或硬盘作为存储介质,二级缓存就属于应用范围. 3.集群范围 在集群

01-05-01-1【Nhibernate (版本3.3.1.4000) 出入江湖】延迟加载及其class和集合(set、bag等)的Lazy属性配置组合对Get和Load方法的影响

这篇文章 http://ayende.com/blog/3988/nhibernate-the-difference-between-get-load-and-querying-by-id One of the more common mistakes that I see people doing with NHibernate is related to how they are loading entities by the primary key. This is because the

01-08-05【Nhibernate (版本3.3.1.4000) 出入江湖】NHibernate二级缓存:第三方MemCache缓存

一.准备工作 [1]根据操作系统(位数)选择下载相应版本的MemCache, MemCache的下载和安装,参看: http://www.cnblogs.com/easy5weikai/p/3760677.html [2]第三方MemCache缓存适配器,下载地址: http://sourceforge.net/projects/nhcontrib/files/ 特别说明: 1.一定要版本一致 MemCache缓存适配器写本文的时候最高版本是:NHCH-3.2.0.GA-bin(不支持高版本的N

01-07-01【Nhibernate (版本3.3.1.4000) 出入江湖】并发控制

Nhibernate 并发控制 [1]悲观并发控制 正在使用数据的操作,加上锁,使用完后解锁释放资源. 使用场景:数据竞争激烈,锁的成本低于回滚事务的成本 缺点:阻塞,可能死锁 [2]乐观并发控制: 所谓乐观,就是乐观的认为其他人没有在用该资源,资源的使用者不加锁. A 读取数据后,如果该数据被别人B修改,产生错误,A回滚事务并重新开始. 使用场景:数据竞争不激烈,回滚事务的成本低于锁的成本. ---------------------------------------------------

01-04-01【Nhibernate (版本3.3.1.4000) 出入江湖】原生的SQL查询

Nhibernate 支持原生的SQL查询 : 1 /// <summary> 2 /// 使用原生的SQL查询 3 /// </summary> 4 /// <param name="datetime"></param> 5 /// <returns></returns> 6 public IList<Customer> GetCustomersByDateTimeUsingSql(string da

01-03-02-1【Nhibernate (版本3.3.1.4000) 出入江湖】CRUP操作--cascade 级联相关

要点: 1. <!--双向关联时要用:inverse:由子表来维护关系,cascade:级联的关系 如果没有这个设置, 插入Customer成功(即使现在Order插入Order抛异常,这时产生了垃圾数据, 好的做法是用事务两者都能插入,避免垃圾数据的产生--> <!--经测试:只需要在主表配置cascade="all",而子表不用配置cascade="all", 当删除主表实体时,子表的级联实体也会被删除--> <!--cascade

01-03-02-2【Nhibernate (版本3.3.1.4000) 出入江湖】CRUP操作-Save方法的一些问题

NHibernate--Save方法: CustomerService.cs 1 public void Save(Customer customer) 2 { 3 ISession session = _sessionManager.GetSession(); 4 ITransaction transaction = session.BeginTransaction(); 5 6 try 7 { 8 session.Save(customer); 9 transaction.Commit();