我有一个名为Category的实体,其中包含相同实体(类别)的许多子类别:
public class Category : Entity
{
public virtual string Name { get; set; }
public virtual IList<Category> SubCategories { get; set; }
public virtual Category ParentCategory { get; set; }
public Category()
{ }
public Category(Category category)
{
SubCategories = category.SubCategories.Where(c => !c.Deleted).Select(c => new Category(c)).ToList();
}
}
这是我的类别映射:
public class CategoryMap : NHibernateMap<Category>
{
public CategoryMap()
{
Map(x => x.Name);
HasMany(x => x.SubCategories).KeyColumn("ParentId").Cascade.AllDeleteOrphan().AsBag();
References(x => x.ParentCategory, "ParentId");
}
}
数据库可以正常运行,我可以轻松地在顶层添加一个新的类别。但是,一旦我尝试在另一个类别下添加类别,就会收到以下异常:
由于StackOverflowException,进程正在终止。
这是我尝试创建类别时的代码:
public Category CreateCategory(CreateCategoryModel model)
{
var category = new Category
{
Name = model.Name,
};
if (model.ParentCategory == null) return category; // Up to here it works fine. - I save the category elsewhere.
var parent = Get(model.ParentCategory.Id);
category.ParentCategory = parent;
parent.SubCategories.Add(category);
_categoryRepository.SaveOrUpdate(parent);
return category; // If I hit these lines of code I get the StackOverflow exception
}
非常感谢您指出我做错了什么或如何解决此问题。
提前感谢:)
也许inverse()可以提供帮助?
HasMany(x => x.SubCategories).KeyColumn("ParentId").Inverse().Cascade.AllDeleteOrphan().AsBag();
我发现了发生StackOverflowException
的问题。在子类别>父类别>子类别>父类别中进行了递归,从而创建了一个无限循环。
我没有像@collenbrecht所说的那样使用Inverse
,但是我采用了另一种方法,只是稍微改变了我的数据结构:
我只保存其ID,而不是将整个ParentCategory对象保存在Category上。然后在需要时我获取整个对象。这消除了无休止的循环并解决了我的问题。
我的类别类现在看起来像这样:
public class Category : Entity
{
public virtual string Name { get; set; }
public virtual IList<Category> SubCategories { get; set; } = new List<Category>();
public virtual long? ParentId { get; set; }
public Category()
{ }
public Category(Category category)
{
SubCategories = new List<Category>();
}
}
以及类似的映射:
public class CategoryMap : NHibernateMap<Category>
{
public CategoryMap()
{
Map(x => x.Name);
Map(x => x.ParentId);
HasMany(x => x.SubCategories).Cascade.AllDeleteOrphan();
}
}
在我的服务下,我可以执行以下操作:
public Category CreateCategory(CreateCategoryModel model)
{
var category = new Category
{
Name = model.Name,
};
if (model.ParentCategory == null)
{
category.ParentId = null;
return category;
}
var parent = Get(model.ParentCategory.Id);
parent.SubCategories.Add(category);
_categoryRepository.SaveOrUpdate(parent);
category.ParentId = model.ParentCategory.Id;
return category;
}