NHibernate:删除的对象将被级联重新保存。替换对象并删除旧对象

NHibernate: deleted object would be re-saved by cascade. Replace object and remove old one

我正在尝试替换 ProgramItem 上的 TimeBlock 对象,然后删除旧的 TimeBlock 对象。这是给我带来问题的删除部分。 我在删除旧的 TimeBlock 对象时遇到一些 'relative' 简单的 nHibernate 问题。

异常:
删除的对象将被级联重新保存(从关联中删除删除的对象)[*.Model.TimeBlock#15]
15是oldTimeBlock的Id

解决这类问题我通常没有任何问题,因为我只是尝试了几乎所有用法:

oldTimeBlock.ProgramItems = new List<ProgramItem>();
programItem.TimeBlock = null;

以任意顺序保存和删除块,并使用 Inverse() 更改映射。
我需要一些新鲜的眼光 - 我怎样才能完成这项工作?

代码:

public class TimeBlock
{
    public virtual int Id { get; set; }
    public virtual IList<ProgramItem> ProgramItems { get; set; }
    ...
}

public class TimeBlockMap : ClassMap<TimeBlock>
{
    public TimeBlockMap()
    {
        Id(x => x.Id);
        HasMany(x => x.ProgramItems).Cascade.SaveUpdate(); // Have tested with Inverse() but seemed to make no difference
    }
}


public class ProgramItem : ImageModel, IIdentifiable
{
    public virtual int Id { get; set; }
    public virtual TimeBlock TimeBlock { get; set; }
    ...
}

public class ProgramItemMap : ClassMap<ProgramItem>
{
    public ProgramItemMap()
    {
        Id(x => x.Id);
        References(x => x.TimeBlock);
    }
}


//Delete old TimeBlock and set new TimeBlock to ProgramItem

var oldTimeBlock = programItem.TimeBlock;

using (var tx = session.BeginTransaction())
{
    oldTimeBlock.ProgramItems = new List<ProgramItem>();
    programItem.TimeBlock = null;
    //session.Save(programItem);
    //session.Save(oldTimeBlock);
    session.Delete(oldTimeBlock);
    tx.Commit(); // location of the exception. If i move the delete oldTimeBlock part below the save programItem part it will still fail in the delete oldTimeBlock part.
}

using (var tx = session.BeginTransaction())
{
    programItem.TimeBlock = timeBlock;
    session.Save(programItem);
    tx.Commit();
}

我试着在这里详细解释发生了什么

  • NHibernate Deleted object would be re-saved by cascade
  • Delete an item from many-to-many relationship

我想说的是,重点在于:ProgramItem 被其他一些集合引用。该集合也被加载到会话中。

最好的起点是 - 在使用 ProgramItem 的任何地方(收集项、参考)将映射更改为 Cascade.None()。然后尝试执行您的删除代码。那会起作用...当然,因为现在级联到位...无法触发该异常。

下一步 - 开始逐块级联。确保您知道什么是允许的,然后您就会知道哪个引用、集合正在重新保存您的对象。

我自己的 experience/approach 是 - 如果您从一个地方删除该项目,如果存在级联,则也从其他地方明确删除它。这可能具有挑战性,但是...