NHibernate 中的自引用实体给对象引用一个未保存的瞬态实例异常

Posted

技术标签:

【中文标题】NHibernate 中的自引用实体给对象引用一个未保存的瞬态实例异常【英文标题】:Self referencing entity in NHibernate gives object references an unsaved transient instance exception 【发布时间】:2017-03-05 06:23:00 【问题描述】:

我有一个名为 Category 的自引用实体。 一个类别可能有一个或多个子类别。一个类别也可能没有子类别。

我已经制作了实体和映射,但我不断收到此异常。

NHibernate.TransientObjectException : 对象引用了一个未保存的对象 瞬态实例 - 在刷新之前保存瞬态实例或 将属性的级联动作设置为可以使它的东西 自动保存。

我在映射部分做错了吗? 是否可以一次保存所有父对象和子对象? 任何帮助将不胜感激。

下面是代码

POCO

public class Category

    private ICollection<Topic> _topics;
    private ICollection<Category> _childCategory;
    private ICollection<Media> _media;
    private Category _parentCategory;

    public virtual int Id  get; set; 
    public virtual string Name  get; set; 
    public virtual string Description  get; set; 
    public virtual bool IsActive  get; set; 

    public virtual Category ParentCategory
    
        get  return _parentCategory ?? (_parentCategory = new Category()); 
        protected set  _parentCategory = value; 
    

    public virtual ICollection<Category> ChildCategory
    
        get  return _childCategory ?? (_childCategory = new List<Category>()); 
        protected set  _childCategory = value; 
    


    public virtual void AddChild(Category childCategory)
    
        childCategory.ParentCategory = this;
    

映射

public class CategoryMapping : IAutoMappingOverride<Category>

    public void Override(AutoMapping<Category> mapping)
    
        mapping.Map(c => c.Name).Length(30);
        mapping.Map(c => c.Description).Length(160);
        mapping.References(x => x.ParentCategory)
            .Cascade.None()
            .Column("ParentCategoryId");
        mapping.HasMany(x => x.ChildCategory)
            .Inverse().Cascade.All()
            .KeyColumn("ParentCategoryId");
    

测试 我正在创建父类别和子类别并尝试一次保存所有类别。

public void CanSaveAllNewObjectGraphFromCategory() 
    #region Categories and Child
    var categories = new sq.Category()
    
        Description = "Category1",
        IsActive = true,
        Name = "Categoy1"
    ;

    var childCat = new List<sq.Category>() 
        new sq.Category()
            Description = "ChildCategory1",
            IsActive = true,
            Name = "CCategoy1"
        ,
        new sq.Category()
            Description = "ChildCategory2",
            IsActive = true,
            Name = "CCategoy2"
        
    ;

    foreach (var item in childCat)
    
        categories.AddChild(item);
    
    #endregion

    using (var tx = _session.BeginTransaction())
    
        _catRepo.AddNewCategory(categories);
        tx.Commit(); // Error occurs when commit is executed.
    

【问题讨论】:

【参考方案1】:

我们需要分配引用的两边

public virtual void AddChild(Category childCategory)

    childCategory.ParentCategory = this;
    // add to collection as well
   _childCategory.Add(childCategory);

【讨论】:

在分配引用的另一端后,我仍然遇到同样的异常。【参考方案2】:

您的错误消息为您提供了两种选择:

在刷新之前保存瞬态实例 将属性的级联操作设置为使其自动保存的内容

第一个选项很简单:在提交事务之前保存每个实例

using (var tx = _session.BeginTransaction())

  foreach(var category in categories)
  
     _session.SaveOrUpdate(category);
  
  _catRepo.AddNewCategory(categories);
  tx.Commit(); 

【讨论】:

以上是关于NHibernate 中的自引用实体给对象引用一个未保存的瞬态实例异常的主要内容,如果未能解决你的问题,请参考以下文章

具有自然键的流畅 NHibernate 引用实体

如何遍历 Thymeleaf 中的自引用实体列表?

实体框架中的自引用/父子关系

是否可以直接在 NHibernate 中设置引用的外键?

Fluent Nhibernate 在使用引用的集合时引用了不正确的列名

CoreData 中的自引用数据对象