多对一级联删除NHibernate导致限制(MySQL 5)

多对一级联删除NHibernate导致限制(MySQL 5),nhibernate,cascade,many-to-one,cascading-deletes,Nhibernate,Cascade,Many To One,Cascading Deletes,我有一个简单的类别类。每个类别可以有零个或多个类别类型的子级。因此,我选择注册一个类别的父级,该类别可以为空,也可以是另一个类别的id。删除类别时,必须同时删除其所有子项(类型为类别) 当NHibernate创建表的架构时,外键存在,但删除时的设置为RESTRICT。 注意:当我在删除时手动更改时:为CASCADE所有操作均按预期进行 我读到过,把孩子和父母联系起来是错误的做法。我不明白为什么。因此,它是有效的。但是NHibernate没有按照我的意愿配置删除时的 我读过关于反向收集和袋子,以及

我有一个简单的
类别
类。每个
类别
可以有零个或多个
类别
类型的子级。因此,我选择注册一个
类别
的父级,该类别可以为空,也可以是另一个
类别
的id。删除
类别
时,必须同时删除其所有子项(类型为
类别

当NHibernate创建表的架构时,外键存在,但删除时的
设置为
RESTRICT
。 注意:当我在删除时手动更改
时:
CASCADE
所有操作均按预期进行

我读到过,把孩子和父母联系起来是错误的做法。我不明白为什么。因此,它是有效的。但是NHibernate没有按照我的意愿配置删除时的

我读过关于反向收集和袋子,以及使用单独的表格。但我对我的方法应该是什么感到困惑

使用此
类别
类如何实现on
delete级联
,为什么

我的映射如下所示:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="BackEnd"
                   namespace="BackEnd.Models">
  <class name="Category">
    <id name="Id">
      <generator class="native"/>
    </id>
    <property name="Name" />
    <many-to-one class="Category" name="Parent" cascade="delete"/>
    <property name="Description" />
  </class>
</hibernate-mapping>

这就是如何在同一个表中映射父子关系,列出对象中的所有子对象,并在删除父对象时删除所有子对象

我最终通过反复试验得到了这个。我试了15次

    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                       assembly="BackEnd"
                       namespace="BackEnd.Models">
      <class name="Category">
        <id name="Id">
          <generator class="native"/>
        </id>
        <property name="Name" />
        <property name="ParentId" />
        <bag name="Children" table="Category" inverse="true" cascade="all-delete-orphan">
          <key column="ParentId" on-delete="cascade"/>
          <one-to-many class="Category"/>
        </bag>
        <property name="Description" />
      </class>
    </hibernate-mapping>

这是我使用的类的代码

/// <summary>
/// The ModelBase takes care of the CRUD (Create, Read, Update, Delete) functionalities for each derived class.
/// public functions here must be virtual, read this: http://thatextramile.be/blog/2009/03/must-everything-be-virtual-with-nhibernate/
/// This is an abstract class as it has no purpose on its own.
/// </summary>
public abstract class ModelBase<T>
{

    /// <summary>
    /// The id by which this transient object is related to a persistent object in database.
    /// </summary>
    public virtual ulong Id { get; set; }


    /// <summary>
    /// Many objects, like categories, issues, etc, can have a parent of the same type
    /// </summary>
    public virtual ulong ParentId { get; set; }

    /// <summary>
    /// The childeren of this object, if any
    /// </summary>
    public virtual IList<T> Children
    {
        get;
        set;
    }

    /// <summary>
    /// Constructor only available for derived classes.
    /// </summary>
    protected ModelBase()
    {
    }

    /// <summary>
    /// Creates or updates this object in database.
    /// </summary>
    public virtual void CreateOrUpdate()
    {
        using(ISession Session = Gate.SessionFactory.OpenSession())
        {
            Session.SaveOrUpdate(((T)((Object)this)));
            Session.Flush();
            Session.Close();
        }
    }

    /// <summary>
    /// Deletes this object from database
    /// </summary>
    public virtual void Delete()
    {
        using (ISession Session = Gate.SessionFactory.OpenSession())
        {
            Session.Delete(((T)((Object)this))); //Needs to be casted as the type of the top most class, or it will fail to get its properties.
            Session.Flush();
            Session.Close();
        }
    }

    /// <summary>
    /// Loads a persistent object (from database) in to a transienst object (variable).
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="Id">The Id of the object by which it is known in database.</param>
    /// <returns>A strong typed object.</returns>
    public static T Load(ulong Id)
    {
        /* TODO: Lazy loading only possible when sessinos remains open.
         * Solve this by adding some kind of OnDispose event that automatically closes the connection when the object is disposed.
         */
        //using (ISession Session = Gate.SessionFactory.OpenSession())
        //{
        //    ModelObject = Session.Load<T>(Id);
        //    Session.Close();
        //}
        ISession Session = Gate.SessionFactory.OpenSession();
        return Session.Load<T>(Id);
    }
}
//
///ModelBase负责每个派生类的CRUD(创建、读取、更新、删除)功能。
///此处的公共函数必须是虚拟的,请阅读以下内容:http://thatextramile.be/blog/2009/03/must-everything-be-virtual-with-nhibernate/
///这是一个抽象类,因为它本身没有任何用途。
/// 
公共抽象类模型库
{
/// 
///此临时对象与数据库中的持久对象相关的id。
/// 
公共虚拟ulong Id{get;set;}
/// 
///许多对象(如类别、问题等)可以具有相同类型的父对象
/// 
公共虚拟ulong ParentId{get;set;}
/// 
///此对象的子对象(如果有)
/// 
公共虚拟现实主义儿童
{
得到;
设置
}
/// 
///构造函数仅适用于派生类。
/// 
受保护的ModelBase()
{
}
/// 
///在数据库中创建或更新此对象。
/// 
公共虚拟空间CreateOrUpdate()
{
使用(ISession Session=Gate.SessionFactory.OpenSession())
{
Session.SaveOrUpdate(((T)((Object)this));
Session.Flush();
Session.Close();
}
}
/// 
///从数据库中删除此对象
/// 
公共虚拟空间删除()
{
使用(ISession Session=Gate.SessionFactory.OpenSession())
{
Session.Delete(((T)((Object)this));//需要强制转换为最顶层类的类型,否则将无法获取其属性。
Session.Flush();
Session.Close();
}
}
/// 
///将持久对象(从数据库)加载到transienst对象(变量)。
/// 
/// 
///数据库中已知对象的Id。
///强类型对象。
公共静态T荷载(ulong Id)
{
/*TODO:只有在Session保持打开状态时才可能延迟加载。
*通过添加某种OnDispose事件来解决此问题,该事件在释放对象时自动关闭连接。
*/
//使用(ISession Session=Gate.SessionFactory.OpenSession())
//{
//ModelObject=Session.Load(Id);
//Session.Close();
//}
ISession Session=Gate.SessionFactory.OpenSession();
返回会话加载(Id);
}
}
最后是从基类派生的category类

/// <summary>
/// A part can be categorized, under one or more, categories.
/// Each category is an instance of this class.
/// </summary>
public class Category : ModelBase<Category>
{
    /// <summary>
    /// The name of the category that is displayed to the user.
    /// </summary>
    public virtual String Name { get; set; }    

    /// <summary>
    /// A description of what this category is about.
    /// </summary>
    public virtual String Description { get; set; }

    /// <summary>
    /// The constructor creates a new category object.
    /// </summary>
    public Category()
    {
    }
}
//
///零件可以在一个或多个类别下进行分类。
///每个类别都是此类的一个实例。
/// 
公共类类别:ModelBase
{
/// 
///显示给用户的类别的名称。
/// 
公共虚拟字符串名称{get;set;}
/// 
///此类别的内容描述。
/// 
公共虚拟字符串描述{get;set;}
/// 
///构造函数创建一个新的类别对象。
/// 
公共类别()
{
}
}

孩子是否也可以有孩子,也可以有孩子等等?是的,他们可以。每个类别只能有一个父级(DataPaes中的ParentId列)。但是,每个家长可以有更多的子类别。因此,可以实现多个级别。我现在正在研究在IList中映射子类别,而不是在加载类别时使用渴望/懒惰加载来加载父类别。网上所有的例子都有两个表格。但是为什么我需要两张桌子呢?