0

私は簡単なcategoryクラスを持っています。それぞれcategoryが 0 個以上の type の子を持つことができますcategorycategoryしたがって、null または別の id の親を登録することにしましたcategory。を削除するcategoryと、そのすべての子 (タイプcategory) も削除する必要があります。

テーブルのスキーマが NHibernate によって作成されると、外部キーは存在しますが、On Delete:に設定されRESTRICTます。注:手動ですべての作品に変更On Delete:すると、期待どおりに動作します。CASCADE

私は、これが子供を親に関連付けるための間違ったアプローチであることを読みました. 理由がわかりません。したがって、それは機能します。しかし、NHibernate は私が望む方法を構成しませんOn Delete

逆コレクションとバッグ、および個別のテーブルの使用について読んだことがあります。しかし、私は自分のアプローチがどうあるべきかについて混乱しています。

delete cascadeこのcategoryクラスでどのように達成するのでしょうか? またその理由は?

私のマッピングは次のようになります。

<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>
4

1 に答える 1

1

これは、同じテーブルで親子関係をマップし、すべての子をオブジェクトにリストし、親が削除されたときにすべての子を削除する方法です。

試行錯誤の末、やっとこれにたどり着きました。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);
    }
}

そして最後に、基本クラスから派生したカテゴリ クラス

/// <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()
    {
    }
}
于 2013-08-06T09:06:49.543 に答える