Объект, ссылающийся на себя в NHibernate, выдает ссылкам на объекты исключение несохраненного временного экземпляра

#nhibernate #orm #fluent-nhibernate #mapping #fluent-nhibernate-mapping

#nhibernate #orm #свободно-nhibernate #сопоставление #fluent-nhibernate-mapping

Вопрос:

У меня есть объект, ссылающийся на себя, с именем 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:

В вашем сообщении об ошибке было предложено два варианта:

  • Сохраните временный экземпляр перед сбросом
  • Установите каскадное действие для свойства на что-то, что сделало бы его автосохраненным

Первый вариант прост: просто сохраните каждый экземпляр перед фиксацией транзакции

 using (var tx = _session.BeginTransaction())
{
  foreach(var category in categories)
  {
     _session.SaveOrUpdate(category);
  }
  _catRepo.AddNewCategory(categories);
  tx.Commit(); 
}
  

Ответ №2:

Нам нужно было бы назначить обе стороны ссылок

 public virtual void AddChild(Category childCategory)
{
    childCategory.ParentCategory = this;
    // add to collection as well
   _childCategory.Add(childCategory);
}
  

Комментарии:

1. Я все еще получаю то же исключение после назначения другой стороны ссылки.