NHibernate级联保存

发布于 2024-08-20 07:29:38 字数 8002 浏览 9 评论 0原文

这是试图将 null 插入 Comment.BlogArticleID。

出现以下 GenericADOException: “无法插入:[NHibernate__OneToMany.BO.Comment][SQL:INSERT INTO Comment (Name) VALUES (?); select SCOPE_IDENTITY()]”

出现以下内部异常: “无法将 NULL 值插入表“Relationships_Test_OneToMany.dbo.Comment”列“BlogArticleID”;列不允许为空值。INSERT 失败。\r\n该语句已终止。”

我需要单向映射。目前提供的答案是关于双向映射。

NHibernate 级联保存是否可以与本机 ID 生成器一起使用?

数据库表:

BlogArticle{ID, Name},如果是 ID,则 Identity=true。

Comment{ID, Name, BlogArticleID},如果是 ID,则 Identity=true。

Comment.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);
        }        
    }

This is trying to insert null into Comment.BlogArticleID.

The following GenericADOException appeared:
"could not insert: [NHibernate__OneToMany.BO.Comment][SQL: INSERT INTO Comment (Name) VALUES (?); select SCOPE_IDENTITY()]"

The following Inner-Exception appeared:
"Cannot insert the value NULL into column 'BlogArticleID', table 'Relationships_Test_OneToMany.dbo.Comment'; column does not allow nulls. INSERT fails.\r\nThe statement has been terminated."

I need a unidirectional mapping. The answer provided yet is talking about bi-directional mapping.

Does NHibernate cascade save works with native ID generator?

DB tables:

BlogArticle{ID, Name}, where in case of ID, Identitity=true.

Comment{ID, Name, BlogArticleID}, where in case of ID, Identitity=true.

Comment.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; }
        }   
    }

Main

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

Repository

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

无人接听 2024-08-27 07:29:38

关联类的键列 (Comment.BlogArticleID) 在数据库中必须可为空。 NHibernate 将插入行并使该列保留为 NULL,然后执行更新以设置键。

将 not-null="true" 添加到关键元素将不起作用,因为此属性仅由架构导出工具使用。

请注意,失败的插入包括对新子行生成的标识的选择。

The key column of the associated class (Comment.BlogArticleID) must be nullable in the database. NHibernate will insert rows leaving this column NULL and then perform an update to set the key.

Adding not-null="true" to the key element would not work, as this attribute is only used by the schema export tool.

Note that the failing insert includes a select for the generated identity for the new child row.

紧拥背影 2024-08-27 07:29:38

您尚未将文章映射到评论:

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

    }

you haven't mapped the Article to the Comment:

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

    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文