nhibernate入门系列: one-to-one映射
nh中的one-to-one(一对一)映射有两种情况, 一种是主键(PrimaryKey)关联, 一种是外健(ForeignKey)关联. 在主键关联的情况下, 显然必须有一个主键是根据别一个主键而来的, nh通过一个特殊的方式来处理这种情况, 要注意的是两个主健名称必须同名.
而外健一对一关联, 需要在one-to-one配置中定义一个property-ref属性, 这个配置属性在当前版本的nh中还没有实现.
Person类的定义如下:
Parson类的映射信息:
这里定义PersonId由数据库自动产生, 在one-to-one中, 定义关联的类为Employee, 并且级联所有操作(保证数据完整性).
Employee类的定义如下:
Employee类的映射信息:
在这个映射文件中, 给Employee类的主健定义了一个特殊的产生方式, 由Person类提供, 实际上就是取Person类的主健值.
在one-to-one中, 定义关联的类为Person, 级联操作也为All.
下面给出了部分测试代码。
public void TestCRUD()
{
Person p = new Person();
p.Name = "test";
Employee e = new Employee();
e.Job = "test";
e.Person = p;
p.Employee = e;
// session.Save( p ); 错误! 不能保存产生主健的一方.
session.Save( e ); // 保存关联的另一方, 同时会保存产生主健的一方.
session.Close();
Employee e2 = session.Load( typeof(Employee), p.PersonId );
Assertion.AssertNotNull( "load fail!", e2 );
Assertion.AssertNotNull( "load fail!", e2.Person );
Person p2 = session.Load( typeof(Person), p.PersonId );
Assertion.AssertNotNull( "load fail!", p2 );
Assertion.AssertNotNull( "load fail!", p2.Employee );
p2.Delete();
}
以上测试代码中session的相关操作请查看相关文档。
如果没有特殊的原因,应该尽量不用one-to-one映射, 而是将两个对象全并起来.
而外健一对一关联, 需要在one-to-one配置中定义一个property-ref属性, 这个配置属性在当前版本的nh中还没有实现.
Person类的定义如下:
public class Person {
public Person() {
}
public int PersonId {
get { return personId; }
set { personId = value; }
}
public string Name {
get { return name; }
set { name = value; }
}
public Employee Employee {
get { return employee; }
set { employee = value; }
}
private int parentId;
private string name;
private Employee employee;
} //class Person
public Person() {
}
public int PersonId {
get { return personId; }
set { personId = value; }
}
public string Name {
get { return name; }
set { name = value; }
}
public Employee Employee {
get { return employee; }
set { employee = value; }
}
private int parentId;
private string name;
private Employee employee;
} //class Person
Parson类的映射信息:
<class name="Person, assemblyname" table="Persons">
<id name="PersonId" column="person_id" type="Int32" unsaved-value="0">
<generator class="identity" />
</id>
<property name="Name" column="Name" type="String"/>
<one-to-one
name="Employee"
cascade="all"
class="Employee, assemblyname"
/>
</class>
Employee类的定义如下:
public class Employee {
public Employee() {
}
public int PersonId {
get { return presonId; }
set { personId = value; }
}
public string Job {
get { return job; }
set { job = value; }
}
public Person Person {
get { return person; }
set { person = value; }
}
private int personId;
private string job;
private Parent person;
} //class Employee
public Employee() {
}
public int PersonId {
get { return presonId; }
set { personId = value; }
}
public string Job {
get { return job; }
set { job = value; }
}
public Person Person {
get { return person; }
set { person = value; }
}
private int personId;
private string job;
private Parent person;
} //class Employee
Employee类的映射信息:
<class name="Employee, AssemblyName" table="Employees">
<id name="personId" column="person_id" type="Int32" unsaved-value="0">
<generator class="foreign">
<param name="property">Person</param>
</generator>
</id>
<property name="Job" column="job" type="String"/>
<one-to-one
name="Person"
cascade="all"
class="Person, AssemblyName"
/>
</class>
<id name="personId" column="person_id" type="Int32" unsaved-value="0">
<generator class="foreign">
<param name="property">Person</param>
</generator>
</id>
<property name="Job" column="job" type="String"/>
<one-to-one
name="Person"
cascade="all"
class="Person, AssemblyName"
/>
</class>
在这个映射文件中, 给Employee类的主健定义了一个特殊的产生方式, 由Person类提供, 实际上就是取Person类的主健值.
在one-to-one中, 定义关联的类为Person, 级联操作也为All.
下面给出了部分测试代码。
public void TestCRUD()
{
Person p = new Person();
p.Name = "test";
Employee e = new Employee();
e.Job = "test";
e.Person = p;
p.Employee = e;
// session.Save( p ); 错误! 不能保存产生主健的一方.
session.Save( e ); // 保存关联的另一方, 同时会保存产生主健的一方.
session.Close();
Employee e2 = session.Load( typeof(Employee), p.PersonId );
Assertion.AssertNotNull( "load fail!", e2 );
Assertion.AssertNotNull( "load fail!", e2.Person );
Person p2 = session.Load( typeof(Person), p.PersonId );
Assertion.AssertNotNull( "load fail!", p2 );
Assertion.AssertNotNull( "load fail!", p2.Employee );
p2.Delete();
}
以上测试代码中session的相关操作请查看相关文档。
如果没有特殊的原因,应该尽量不用one-to-one映射, 而是将两个对象全并起来.