Nhibernate不会从集合中删除子项
首先是地图Nhibernate不会从集合中删除子项,nhibernate,collections,parent-child,Nhibernate,Collections,Parent Child,首先是地图 <set name="Comments" table="cm_events_venue_comment" inverse="true" lazy="true" generic="true" cascade="all-delete-orphan" batch-size="10" order-by="dateCreated ASC"> <cache usage="read-write" /> <key colu
<set name="Comments" table="cm_events_venue_comment" inverse="true"
lazy="true" generic="true" cascade="all-delete-orphan"
batch-size="10" order-by="dateCreated ASC">
<cache usage="read-write" />
<key column="venueId" />
<one-to-many class="VenueComment" />
</set>
通过测试
[Test]
public void CanSaveAndDeleteComments()
{
User u = TestDataHelper.CreateUser("Sir", "Talkalot");
VenueComment comment;
Venue v = GetVenueById();
PerformInTransaction(() =>
{
userRepository.SaveOrUpdate(u);
comment = new VenueComment()
{
Commenter = u,
Text = "I like ifs and buts and i cannot lie..",
DateCreated = DateTime.Now
};
v.AddComment(comment);
comment = new VenueComment()
{
Commenter = u,
Text = "And words ending in 'ly'",
DateCreated = DateTime.Now
};
v.AddComment(comment);
Assert.DoesNotThrow(()=>venueRepository.SaveOrUpdate(v));
});
// Test retrieval
Session.Evict(v);
v = GetVenueById();
v.Comments.Count.ShouldEqual(2);
var c = v.Comments.FirstOrDefault<VenueComment>();
c.Commenter.Id.ShouldEqual(u.Id);
// and deletion
PerformInTransaction(() =>
{
v.RemoveComment(c);
});
Session.Evict(v);
v = GetVenueById();
v.Comments.Count.ShouldEqual(1);
}
[测试]
public void可以保存和删除注释()
{
用户u=TestDataHelper.CreateUser(“Sir”、“Talkalot”);
维努埃评论;
地点v=GetVenueById();
执行事务(()=>
{
userRepository.SaveOrUpdate(u);
comment=new-VenueComment()
{
评论员=u,
Text=“我喜欢如果和但是,我不能撒谎…”,
DateCreated=DateTime.Now
};
v、 添加评论(评论);
comment=new-VenueComment()
{
评论员=u,
Text=“和以“ly”结尾的单词”,
DateCreated=DateTime.Now
};
v、 添加评论(评论);
Assert.doesnothrow(()=>venueRepository.SaveOrUpdate(v));
});
//测试检索
会议.驱逐(五);
v=GetVenueById();
v、 注释.计数.应等于(2);
var c=v.Comments.FirstOrDefault();
c、 注释者Id.ShouldEqual(u.Id);
//和删除
执行事务(()=>
{
v、 清除指令(c);
});
会议.驱逐(五);
v=GetVenueById();
v、 注释.计数.应等于(1);
}
我的问题来自我应用程序的控制器
[Authenticate, AcceptAjax]
public ActionResult DeleteComment(int id)
{
return PerformInTransaction<ActionResult>(() =>
{
var comment = commonDao.GetObjectById<VenueComment>(id);
if (comment == null)
return JsonFailure("Comment not found");
if (comment.Commenter.Id == CurrentUser.Id ||
AuthUtil.IsAdministrator()) //
{
var venue = comment.Venue;
venue.RemoveComment(comment);
return JsonSuccess(id);
}
return JsonFailure("You can only delete comments you created.");
});
}
[验证,接受JAX]
public ActionResult DeleteComment(内部id)
{
返回性能事务(()=>
{
var comment=commonDao.GetObjectById(id);
if(注释==null)
返回JsonFailure(“未找到注释”);
if(comment.Commenter.Id==CurrentUser.Id||
AuthUtil.IsAdministrator())//
{
var场馆=评论。场馆;
地点:搬迁通知(备注);
返回JsonSuccess(id);
}
返回JsonFailure(“您只能删除您创建的注释”);
});
}
根据Log4Net,没有发布删除操作。正如我所说,上面的测试通过了,因此映射应该是正确的
有什么线索吗?根据我的经验,当我忘记提交事务或正确关闭并刷新会话时,就会发生这种情况。会话和事务管理也是您的测试和演示者之间的一个显著区别。如果您查看集合类型属性映射的
逆属性的文档,您会发现设置逆=“false”
指示NHibernate监视父对象(包含集合的对象)以更改集合,并基于父对象的子集合上的添加/删除来插入/删除子对象
但是,当您设置inverse=“true”
时,您是在指示NHibernate监视子对象,以便将引用属性的更改返回到父对象。因此,当您设置子对象的父引用属性时,NHibernate随后将去修改关联
看起来您不想在父对象的子集合上设置inverse=“true”
增编:
RemoveComment
可以解除父项与子项的关联(如中所示,设置child.parent=null
)。但是如果它没有解除子项与会话的关联,并且如果集合标记为reverse=“true”
指示子级拥有关联而不是拥有关联的集合,则NHibernate不会发送删除
。如果对象应该被删除,NHibernate只会发送删除
,如果集合拥有关联(inverse=“false”
)并且集合的级联设置为包括删除,并且对象从集合中删除,或者b)如果对象从会话中删除,
。。。。
这是两个代码基的合并
一个旧的dao(commonDao)有一个bug,其中内部会话属性根据属性访问从会话工厂创建新会话,因此对象加载和flush()之间存在不同的会话
较新的代码使用基于S#arp体系结构的存储库,该体系结构具有自动会话管理功能,因此问题不会出现在单元测试中 奇怪的是,测试按原样通过了映射。RemoveComment
可能会解除父项与子项的关联(如中所示,setchild.parent=null
)。但是,如果它没有解除子对象与会话的关联,并且如果集合标记为reverse=“true”
,表示子对象拥有关联,而不是拥有关联的集合,那么NHibernate将不会发送删除
。NHibernate只会在对象应该被删除的情况下发送一个delete
,如果集合拥有该对象(inverse=“false”
),并且该对象被从集合中删除,或者如果该对象被从会话中删除,那么您的评论会让我想到一些古怪的会话处理代码,谢谢。看看我的答案。。。