首先是映射,
<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);
}
我的问题出现在我的应用程序的控制器中,
[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.");
});
}
根据Log4Net,没有发布删除。正如我所说,上述测试通过,因此映射应该是正确的。
任何线索?
答案 0 :(得分:4)
如果您查看集合类型属性映射的inverse
属性的文档,您会发现设置inverse="false"
指示NHibernate监视父对象(包含集合的对象)更改集合,以及根据父项的子集合添加/删除插入/删除子对象。
但是,当你设置inverse="true"
时,你正在指示NHibernate监视子对象以更改引用属性回到父对象。因此,当您设置子级的父引用属性时,NHibernate将继续修改关联。
看起来你不想在父母的子集合上设置inverse="true"
。
RemoveComment
可以取消父母与子女的关联(例如,设置child.Parent = null
)。但是如果它也没有将孩子从Session
解除关联,并且如果集合被标记为inverse="true"
,表明孩子拥有该关联而不是拥有该关联的集合,那么NHibernate将不会发送一个delete
。如果对象应该被删除,NHibernate将只发送delete
- a)如果集合拥有关联(inverse="false"
)并且集合的级联设置为包含删除并且对象从中删除集合,或b)如果从Session
删除对象。
答案 1 :(得分:1)
根据我的经验,当我忘记提交交易或正确关闭时,会发生这种情况。刷新会话。会话&amp;事务管理也是测试和演示者之间的显着差异。
答案 2 :(得分:1)
神秘解决了.... 这是两个代码库合并的案例。
一个旧的dao(commonDao)有一个错误,其中内部Session属性是从每个属性访问的会话工厂创建一个新会话,因此在对象加载和flush()之间存在不同的会话。
较新的代码使用基于S#arp架构的存储库,它具有自动会话管理功能,因此问题没有出现在单元测试中。