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
可能会解除父项与子项的关联(如中所示,set
child.parent=null
)。但是,如果它没有解除子对象与
会话的关联,并且如果集合标记为
reverse=“true”
,表示子对象拥有关联,而不是拥有关联的集合,那么NHibernate将不会发送
删除
。NHibernate只会在对象应该被删除的情况下发送一个
delete
,如果集合拥有该对象(
inverse=“false”
),并且该对象被从集合中删除,或者如果该对象被从
会话中删除,那么您的评论会让我想到一些古怪的会话处理代码,谢谢。看看我的答案。。。