这就是如何在同一个表中映射父子关系,列出所有子对象到您的对象,并在删除父对象时删除所有子对象。
我终于通过反复试验得到了这个。我花了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()
{
}
}