我对nhibernate有一种奇怪的行为。问题是 nhibernate在删除实体之前执行更新。 我有一个Category类和一个Product类。分类有一袋 产品。当我从Category中删除产品时,nhibernate就会这样做 以下:
这是映射
<class name="Category">
<id name="Id">
<generator class="hilo" />
</id>
<property name="Name" lazy="false" length="20" />
<bag name="Products" cascade="all-delete-orphan" lazy="false"
inverse="false">
<key column="CategoryId" />
<one-to-many class="Product" />
</bag>
</class>
<class name="Product">
<id name="Id">
<generator class="hilo" />
</id>
<property name="Name" lazy="false" />
<property name="Discontinued" lazy="false" />
<property name="Price" lazy="false" />
<many-to-one name="Category"
class="Category"
column="CategoryId"
cascade="none" />
</class>
这是代码
using (var session = NHibernateHelper.OpenSession())
using (var transaction = session.BeginTransaction())
{
var c1 = session.Load<Category>(32768);
c1.Ps.RemoveAt(0);
session.SaveOrUpdate(c1);
transaction.Commit();
}
这是结果:
exec sp_executesql N'UPDATE Product SET CategoryId = null WHERE
CategoryId = @p0 AND Id = @p1',N'@p0 int,@p1 int',@p0=32768,@p1=65537
go
exec sp_executesql N'DELETE FROM Product WHERE Id = @p0',N'@p0
int',@p0=65537
go
任何人都可以解释这种奇怪的行为吗?
感谢。
答案 0 :(得分:12)
对类别上的产品包定义更改为true。将inverse设置为false告诉NHibernate Category对象是关系中键的所有者。
在Products集合上将inverse设置为false,NHibernate将Category视为关系的所有者。因此,当Products集合更改时,它会发出update语句以从Category中删除Product。然后删除是因为产品已被删除。
答案 1 :(得分:0)
Ps
不是一个非常具有描述性的属性。在这种情况下发生的是,由于您删除产品的方式(通过从类别中的集合中删除它然后保存类别),NHibernate首先从产品中删除对类别的引用,因为该产品没有更长属于类别(这是对象和表之间的关键转换;在OOP中,引用由包含对象保存,而在SQL中由包含对象保存)。现在记录不属于任何类别;它是孤儿,你告诉NHibernate清除其级联行为中的孤立引用,因此它会执行删除。
如果你只想用一个SQL语句来做,试试这个:
using (var session = NHibernateHelper.OpenSession())
using (var transaction = session.BeginTransaction())
{
var c1 = session.Load<Category>(32768);
var toDelete = c1.Ps[0];
c1.Ps.RemoveAt(0);
session.Delete(toDelete);
transaction.Commit();
//you shouldn't need to update the c1 object
}
答案 2 :(得分:-2)
这种行为对我来说很正常。我对NHibernate没什么经验,但为了删除记录,我相信你通常会调用ISession.Delete
方法,传入代表你要删除的记录的对象。
在您的情况下,您可以执行以下操作:
// delete a product
session.Delete(c1.Ps[0]);
或者,更清楚:
// find the product that I want to delete
var product = c1.Ps[0];
// now delete it
session.Delete(product);
您的代码似乎采用了一种删除产品记录的迂回方式。您的代码未明确删除产品,而是将产品记录与该类别记录取消关联。这就是NHibernate正在进行更新的原因。
请注意,在Category类中,您已将与Product类关系的“cascade”属性定义为:cascade="all-delete-orphan"
。因为你的update语句导致产品记录被孤立,所以NHibernate可能会认识到应该根据你的级联设置删除产品记录,所以我认为这就是它决定执行delete语句的原因。