Каскадное сохранение NHibernate

Это пытается вставить null в Comment.BlogArticleID.

Появилось следующее исключение GenericADOException: «не удалось вставить: [NHibernate__OneToMany.BO.Comment] [SQL: INSERT INTO Comment (Name) VALUES (?); Select SCOPE_IDENTITY ()]»

Появилось следующее внутреннее исключение: «Невозможно вставить значение NULL в столбец« BlogArticleID », таблица« Relationships_Test_OneToMany.dbo.Comment »; столбец не допускает значений NULL. INSERT не работает. \ R \ nОператор был прерван».

Мне нужно однонаправленное отображение. Ответ пока что касается двунаправленного отображения.

Каскадное сохранение NHibernate работает с собственным генератором идентификаторов?

Таблицы БД:

BlogArticle {ID, Name}, где в случае ID Identitity = true.

Комментарий {ID, Name, BlogArticleID}, где в случае ID Identitity = true.

Комментарий.hbm.xml

<hibernate-mapping
  xmlns="urn:nhibernate-mapping-2.2"
  assembly="NHibernate__OneToMany.BO"
  namespace="NHibernate__OneToMany.BO"
  default-access="property">

  <class name="Comment" table="Comment">
    <id name="ID">
      <generator class="native" />
    </id>

    <property name="Name" />
  </class>
</hibernate-mapping>

public class Comment
    {
        private int _id;
        public virtual int ID
        {
            get { return _id; }
            set { _id = value; }
        }

        public Comment()
        {
        }

        public Comment(string name)
        {
            this._name = name;
        }

        private string _name;
        public virtual string Name
        {
            get { return _name; }
            set { _name = value; }
        }   
    }

BlogArticle.hbm.xml

<hibernate-mapping 
  xmlns="urn:nhibernate-mapping-2.2"
  namespace="NHibernate__OneToMany.BO"
  assembly="NHibernate__OneToMany.BO"
  default-access="property">
  <class name="BlogArticle"  table="BlogArticle">
    <id name="ID">
      <generator class="native" />
    </id>

    <property name="Name" column="Name" />

    <bag name="Comments" cascade="all" >
      <key column="BlogArticleID" />
      <one-to-many class="Comment" />
    </bag>
  </class>
</hibernate-mapping>


public class BlogArticle
    {
        private int _id;
        public virtual int ID
        {
            get { return _id; }
            set { _id = value; }
        }

        private string _name;
        public virtual string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        private IList _depts;
        public virtual IList Comments
        {
            get { return _depts; }
            set { _depts = value; }
        }   
    }

Главный

class Program
{
    static void Main(string[] args)
    {
        BlogArticle ba = new BlogArticle();
        ba.Name = "Humanity";
        ba.Comments = new List<Comment>();
        ba.Comments.Add(new Comment("Comm1"));
        ba.Comments.Add(new Comment("Comm2"));
        ba.Comments.Add(new Comment("Comm3"));

        Repository<BlogArticle> rep = new Repository<BlogArticle>();
        rep.Save(ba);
    }
}

Репозиторий

public class Repository<T> : IRepository<T>
    {
        ISession _session;

        public Repository()
        {
            _session = SessionFactoryManager.SessionFactory.OpenSession();
        }

        private void Commit()
        {
            if (_session.Transaction.IsActive)
            {
                _session.Transaction.Commit();
            }
        }

        private void Rollback()
        {
            if (_session.Transaction.IsActive)
            {
                _session.Transaction.Rollback();
                //_session.Clear();
            }
        }

        private void BeginTransaction()
        {
            _session.BeginTransaction();
        }

        public void Save(T obj)
        {
            try
            {
                this.BeginTransaction();

                _session.Save(obj);                

                this.Commit();
            }
            catch (Exception ex)
            {
                this.Rollback();

                throw ex;
            }            
        }

        void IRepository<T>.Save(IList<T> objs)
        {
            try
            {
                this.BeginTransaction();

                for (Int32 I = 0; I < objs.Count; ++I)
                {
                    _session.Save(objs[I]);
                }

                this.Commit();
            }
            catch (Exception ex)
            {
                this.Rollback();

                throw ex;
            }
        }

        void IRepository<T>.Update(T obj)
        {
            try
            {
                this.BeginTransaction();

                _session.Update(obj);

                this.Commit();
            }
            catch (Exception ex)
            {
                this.Rollback();

                throw ex;
            }
        }

        void IRepository<T>.Update(IList<T> objs)
        {
            try
            {
                this.BeginTransaction();

                for (Int32 I = 0; I < objs.Count; ++I)
                {
                    _session.Update(objs[I]);
                }

                this.Commit();
            }
            catch (Exception ex)
            {
                this.Rollback();

                throw ex;
            }
        }

        void IRepository<T>.Delete(T obj)
        {
            try
            {
                this.BeginTransaction();

                _session.Delete(obj);

                this.Commit();
            }
            catch (Exception ex)
            {
                this.Rollback();

                throw ex;
            }  
        }

        void IRepository<T>.Delete(IList<T> objs)
        {
            try
            {
                this.BeginTransaction();

                for (Int32 I = 0; I < objs.Count; ++I)
                {
                    _session.Delete(objs[I]);
                }

                this.Commit();
            }
            catch (Exception ex)
            {
                this.Rollback();

                throw ex;
            }
        }

        T IRepository<T>.Load<T>(object id)
        {
            return _session.Load<T>(id);
        }

        public IList<T> Get<T>(int pageIndex, int pageSize)
        {
            ICriteria criteria = _session.CreateCriteria(typeof(T));
            criteria.SetFirstResult(pageIndex * pageSize);
            if (pageSize > 0)
            {
                criteria.SetMaxResults(pageSize);
            }
            return criteria.List<T>();
        }

        public T Get<T>(object id)
        {
            return _session.Get<T>(id);
        }

        public IList<T> Get<T>()
        {
            return Get<T>(0, 0);
        }

        public IList<T> Get<T>(string propertyName, bool Ascending)
        {
            Order cr1 = new Order(propertyName, Ascending);

            IList<T> objsResult = _session.CreateCriteria(typeof(T)).AddOrder(cr1).List<T>();

            return objsResult;
        }

        public IList<T> Find<T>(IList<string> strs)
        {
            System.Collections.Generic.IList<NHibernate.Criterion.ICriterion> objs = new System.Collections.Generic.List<ICriterion>();
            foreach (string s in strs)
            {
                NHibernate.Criterion.ICriterion cr1 = NHibernate.Criterion.Expression.Sql(s);
                objs.Add(cr1);
            }
            ICriteria criteria = _session.CreateCriteria(typeof(T));
            foreach (ICriterion rest in objs)
                _session.CreateCriteria(typeof(T)).Add(rest);

            criteria.SetFirstResult(0);
            return criteria.List<T>();
        }

        public void Detach(T item)
        {
            _session.Evict(item);
        }        
    }

person Community    schedule 06.02.2010    source источник
comment
Ознакомьтесь с stackoverflow.com/questions/146604/   -  person    schedule 06.02.2010
comment
может быть <key column="BlogArticleID" not-null="true" />?   -  person dotjoe    schedule 08.02.2010
comment
Вы пробовали изменить ссылку, опубликованную Исааком Камброном? Кроме того, с какой версией NH вы работаете?   -  person Jaguar    schedule 17.02.2010


Ответы (2)


Ключевой столбец связанного класса (Comment.BlogArticleID) должен иметь значение NULL в базе данных. NHibernate вставит строки, оставляя этот столбец NULL, а затем выполнит обновление, чтобы установить ключ.

Добавление not-null = "true" к ключевому элементу не сработает, поскольку этот атрибут используется только инструментом экспорта схемы.

Обратите внимание, что неудачная вставка включает выбор для сгенерированного удостоверения для новой дочерней строки.

person Community    schedule 18.02.2010
comment
На самом деле, он не может быть ненулевым в отображении, а не в базе данных. Я использую Nhibernate 3.3, и моя сумка имеет значение NULL, и мое отношение Many to One также допускает значение NULL, но база данных настроена так, чтобы не принимать нулевые значения, и это работает, когда я сохраняю каскад - person Daniel; 13.12.2013

вы не сопоставили статью с комментарием:

<hibernate-mapping
  xmlns="urn:nhibernate-mapping-2.2"
  assembly="NHibernate__OneToMany.BO"
  namespace="NHibernate__OneToMany.BO"
  default-access="property">

  <class name="Comment" table="Comment">
    <id name="ID">
      <generator class="native" />
    </id>

    <property name="Name" />
    <many-to-one name="BlogArticle" column="BlogArticleID" />   <----------
  </class>
</hibernate-mapping>

public class Comment
    {
        private int _id;
        public virtual int ID
        {
            get { return _id; }
            set { _id = value; }
        }

        public Comment() { }

        public Comment(int id, string name, BlogArticle article) <------------
        {
            this._id = id;
            this._name = name;
            this._blogArticle = article; <------------
        }

        private string _name;
        public virtual string Name
        {
            get { return _name; }
            set { _name = value; }
        }   

        private BlogArticle _blogArticle;       <------------
        public virtual BlogArticle Name       <------------
        {
            get { return _blogArticle; }       <------------
            set { _blogArticle= value; }       <------------
        }   

    }
person Jaguar    schedule 13.02.2010
comment
Мне нужно однонаправленное отображение. В вашем решении используется двунаправленное сопоставление. Двунаправленный проще. - person user366312; 17.02.2010
comment
ну, вы этого не сказали .... вы можете опубликовать код, который вы используете для вставки? - person Jaguar; 17.02.2010
comment
Пожалуйста, смотрите обновление. Я думаю, что в моем коде вставки особо не на что смотреть. - person user366312; 17.02.2010
comment
А также не могли бы вы сказать что-нибудь об исключении: Unexpected row count: 0; Ожидается: 1. Это происходит периодически. - person user366312; 17.02.2010
comment
почему вы назначаете идентификатор комментариям, сгенерированным, когда вы установили ‹generator class = native /›? это может вызвать ошибочное поведение (и, возможно, исключение, которое вы упомянули) - person Jaguar; 17.02.2010
comment
Я сделал исправление, не назначив идентификатор для комментариев, и появилось следующее внутреннее исключение: невозможно вставить значение NULL в столбец BlogArticleID, таблицу Relationships_Test_OneToMany.dbo.Comment; столбец не допускает значений NULL. Ошибка INSERT. \ R \ nОператор прерван. - person user366312; 18.02.2010
comment
Крутая кривая обучения NHibernate заставляет меня все больше и больше разочаровываться. - person user366312; 18.02.2010