NHibernate: deleted object would be re-saved by ca

2019-02-14 16:17发布

问题:

I am trying to replace at TimeBlock object on a ProgramItem and then delete the old TimeBlock object. It is the delete part that gives me problems. I have some 'relative' simple nHibernate probelms deleting the old TimeBlock object.

Exception:
deleted object would be re-saved by cascade (remove deleted object from associations)[*.Model.TimeBlock#15]
15 is the Id of the oldTimeBlock

I usaully doesn't have any problems solving this kind of issue by I just tried amost any usages of:

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

and the save and delete blocks in any order and changing the mapping with Inverse().
I need some fresh eyes - how could I make this work?

Code:

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();
}

回答1:

I tried explain what is happening in detail here

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

I would say, that the point is here: the ProgramItem is referenced by some other collection. And that collection was also loaded into the session.

The best place where to start is - wherever is ProgramItem used (collection item, reference) change the mapping to Cascade.None(). Then try to execute your deletion code. That will work... surely, becuase now cascading in place... no way how to trigger that exception.

Next - start cascading by pieces. Be sure you know what is allowed, and then you will know which reference, collection is re-saving your object.

My own experience/approach is - if you delete the item from one place, explicitly delete it from others as well, if there is cascade. It could be challenging, but...