简体   繁体   English

NHibernate级联保存

[英]NHibernate cascading save

This is trying to insert null into Comment.BlogArticleID. 这是尝试在Comment.BlogArticleID中插入null。

The following GenericADOException appeared: "could not insert: [NHibernate__OneToMany.BO.Comment][SQL: INSERT INTO Comment (Name) VALUES (?); select SCOPE_IDENTITY()]" 出现以下GenericADOException:“无法插入:[NHibernate__OneToMany.BO.Comment] [SQL:INSERT INTO注释(名称)VALUES(?);选择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." 出现以下内部异常:“无法将值NULL插入列'BlogArticleID',表'Relationships_Test_OneToMany.dbo.Comment';列不允许空值.INSERT失败。\\ r \\ n语句已终止。”

I need a unidirectional mapping. 我需要一个单向映射。 The answer provided yet is talking about bi-directional mapping. 提供的答案还在谈论双向映射。

Does NHibernate cascade save works with native ID generator? NHibernate级联保存是否适用于本机ID生成器?

DB tables: 数据库表:

BlogArticle{ID, Name}, where in case of ID, Identitity=true. BlogArticle {ID,Name},如果是ID,则Identitity = true。

Comment{ID, Name, BlogArticleID}, where in case of ID, Identitity=true. 注释{ID,Name,BlogArticleID},如果是ID,则Identitity = true。

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

The key column of the associated class (Comment.BlogArticleID) must be nullable in the database . 关联类的键列(Comment.BlogArticleID)必须在数据库中可为空 NHibernate will insert rows leaving this column NULL and then perform an update to set the key. NHibernate将插入将此列留空的行,然后执行更新以设置密钥。

Adding not-null="true" to the key element would not work, as this attribute is only used by the schema export tool. 将not-null =“true”添加到key元素将不起作用,因为此属性仅由架构导出工具使用。

Note that the failing insert includes a select for the generated identity for the new child row. 请注意,失败的插入包括为新子行生成的标识的选择。

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

    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM