How to save a child with assigned id in nhibernate

后端 未结 3 1599
面向向阳花
面向向阳花 2020-12-01 10:38

I have two classes:

public class Parent
{
    public virtual long? ID { get; set; } // native
    public virtual IList Children { get; set; }
           


        
相关标签:
3条回答
  • 2020-12-01 11:17

    Calling session.SaveOrUpdate( childObject ) should solve the problem.

    0 讨论(0)
  • 2020-12-01 11:22

    I'm not 100% sure if this is the same problem you are having, but my database is 100% assigned id (ugh) and I had to create an Interceptor that kept track of whether a child is or isn't persisted for cascades to work.

    The code is cut/paste (which is why it has dumb names... I didn't understand 100% at first!), and I initially got 90% of it from online documentation (which I can't find via google right now ... sorry):

    Base class you put on object that has an assigned ID you want to cascade:

    public class Persistent
    {
        private bool _saved = false;
    
        public virtual void OnSave()
        {
            _saved = true;
        }
    
        public virtual void OnLoad()
        {
            _saved = true;
        }
    
        public virtual bool IsSaved
        {
            get { return _saved; }
        }
    }
    

    The interceptor you add to session:

    public class TrackingNumberInterceptor : EmptyInterceptor
    {
        public override bool? IsTransient(object entity)
        {
            if (entity is Persistent)
            {
                return !((Persistent)entity).IsSaved;
            }
            else
            {
                return null;
            }
        }
    
        public override bool OnLoad(object entity, object id, object[] state, string[] propertyNames, IType[] types)
        {
            if (entity is Persistent) ((Persistent)entity).OnLoad();
            return false;
        }
    
        public override bool OnSave(object entity, object id, object[] state, string[] propertyNames, IType[] types)
        {
            if (entity is Persistent) ((Persistent)entity).OnSave();
            return false;
        }
    }
    

    Basically the idea is that since NHibernate doesn't know if an assigned id entity is persisted or not, you keep track for it.

    By default the object starts with persisted (_saved) at false. When the entity is either loaded or saved by NHibernate, the trigger sets the objects persisted (_saved) flag to true.

    So for a fresh item that isn't persisted, it starts at false and stays false because NHibernate has never saved or loaded it. When NHibernate checks whether the child is transient, the trigger responds that it is transient, and a save happens which marks the child as persisted. Also now any future use will require a load which again marks it as persisted.

    0 讨论(0)
  • 2020-12-01 11:27

    When cascading from a parent to a child, NHibernate uses the SaveOrUpdate method. You are correct that NHibernate need some way to determine whether it should perform an insert or an update. It will look at three different fields for an unsaved value to determine if the entity is new.

    1. Id
    2. Version
    3. Timestamp

    With an assigned Id, you will need either a Version or Timestamp field in order to indicate that the entity is new.

    An alternative would be to call Save() on the children explicitly.

    0 讨论(0)
提交回复
热议问题