咱就入个门之NHibernate映射文件配置(二)

旧地址:http://blog.canself.com/nhibernate_onetomany/

上一篇主要介绍了NHibernate映射文件的基础配置,这篇我们介绍下NHibernate的一对多及多对一配置(文中我直接使用双向关联,即一和多两端都配置,开发中可以只使用一端),同时略带介绍下NHibernate.Mapping.Attributes方式配置表映射。

首先,我们使用Parent和Children两个类,Parent为一端,Chrildren为多端。

下面是Parent类和映射文件配置:

1
2
3
4
5
6
7
8
9
10
11
namespace NHibernateStudy.OneToMany
{
public class Parent
{
public virtual String Id { get; set; }

public virtual String Name { get; set; }

public virtual IList<Children> Children { get; set; }
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernateStudy" namespace="NHibernateStudy.OneToMany">
<class name="Parent" table="parents">
<id name="Id" column="id" type="String">
<generator class="uuid.hex" />
</id>
<property name="Name" column="name" type="String" />
<bag name="Children" table="children" inverse="true" cascade="all">
<key column="parentid" />
<one-to-many class="NHibernateStudy.OneToMany.Children"/>
</bag>
</class>
</hibernate-mapping>

其中cascade我配置了all,保证级联更新,若有其他需求可以使用none等值。

下面是Children类及配置文件:

1
2
3
4
5
6
7
8
9
10
11
namespace NHibernateStudy.OneToMany
{
public class Children
{
public virtual string Id { get; set; }

public virtual string Name { get; set; }

public virtual Parent TheParent { get; set; }
}
}

其中需要注意,many-to-one中,column写的是当前表的字段——外键;而配置一端时,其中key里的column配置的是多端的字段,即子表里的外键,而非当期表字段。

配置文件中添加mapping:

1
2
<mapping resource="NHibernateStudy.OneToMany.Parent.hbm.xml" assembly="NHibernateStudy" />
<mapping resource="NHibernateStudy.OneToMany.Children.hbm.xml" assembly="NHibernateStudy" />

下面是使用方式过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#region 添加一对多关联数据
Parent parent = new Parent();
parent.Name = "parent" + DateTime.Now.ToString("MMddHHmmss");
parent.Children = new List<Children>();
Children child = new Children();
child.Name = "child" + DateTime.Now.ToString("MMddHHmmss");
child.TheParent = parent;
parent.Children.Clear();
parent.Children.Add(child);
session.Save(parent);
session.BeginTransaction().Commit();
#endregion

#region 查看多对一数据
IList<Children> children = session.CreateCriteria<Children>().List<Children>();
foreach (var item in children)
{
Parent itemparent = item.TheParent ?? new Parent();
Console.WriteLine(string.Format("ChildId:{0} Name:{1} \r\nParentId:{2} ParentName:{3}", item.Id, item.Name, itemparent.Id, itemparent.Name));
}
#endregion

下面介绍下Attributes方式配置映射文件。
首先添加NHibernate.Mapping.Attributes引用,可以在nuget中查找。

下面是配置的类,使用此法可以避免使用hbm.xml的繁琐,其中的属性与hbm.xml中的基本一致。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
namespace NHibernateStudy
{
[Serializable]
[Class(Table = "animals", Name = "NHibernateStudy.Animal,NHibernateStudy")]
public class Animal
{
/// <summary>
/// 主键
/// </summary>
[Id(Name = "Id", Column = "id", TypeType = typeof(string))]
[Key]
[Generator(Class = "uuid.hex")]
public virtual String Id { get; set; }

[Property(Name = "Name", Column = "name")]
public virtual string Name { get; set; }

}
}

不过需要注意的是,在代码中使用的时候,需要使用以下方式加载Mapping。

1
2
3
4
5
6
7
8
9
10
11
12
13
Configuration cfg = new Configuration();

MemoryStream stream = new MemoryStream();
NHibernate.Mapping.Attributes.HbmSerializer.Default.Validate = true;
NHibernate.Mapping.Attributes.HbmSerializer.Default.Serialize(
stream, System.Reflection.Assembly.GetExecutingAssembly());
stream.Position = 0; // Rewind
cfg.Configure();
cfg.AddInputStream(stream); // Use the stream here
stream.Close();

ISessionFactory sessionFactory =cfg.BuildSessionFactory();
ISession session = sessionFactory.OpenSession();

下面是具体使用过程:

1
2
3
4
5
6
7
8
9
10
11
12
#region NHibernate.Mapping.Attributes映射添加一条数据
Animal a = new Animal();
a.Name = "animal" + DateTime.Now.ToString("MMddHHmmss");
session.Save(a);
session.BeginTransaction().Commit();

IList<Animal> an = session.CreateCriteria<Animal>().List<Animal>();
foreach (var item in an)
{
Console.WriteLine("Animal——ID: " + item.Id + " Name:" + item.Name);
}
#endregion