随笔-82  评论-920  文章-0  trackbacks-56

NHibernate的关联映射(one-to-one,one-to-many,many-to-many)以及cascade分析

一、典型设置

cascade:(默认为none)级联。指明哪些操作会从对象级联到关联的对象。

inverse: (默认为false) 标记这个集合作为双向关联关系中的方向一端。在双向关联时才需要设置。在设为false的一端对cascade进行维护。处于性能的考虑,一般在数据少的一端或者被依赖端设置inverse="true",而让数据多的一段维护cascade。

1.one-to-one

1.1 数据库表结构

其中T_Person为主表,T_Employee为子表。T_Employee的PersonId参照T_Peson的PersonId。

1.2 示例映射类文件

/*
/*作者:DDL
/*联系:
http://renrenqq.cnblogs.com/
*/


using System;

namespace DDLLY.TestNHibernate.TestAssociation.OneToOne
{
    
/// <summary>
    
///    
    
/// </summary>

    [Serializable]
    
public class Person
    
{
        
Private Members

        
Default ( Empty ) Class Constuctor // End of Default ( Empty ) Class Constuctor

        
Public Properties

        
Public Functions

        
Equals And HashCode Overrides
    }

}

/*
/*作者:DDL
/*联系:
http://renrenqq.cnblogs.com/
*/


using System;

namespace DDLLY.TestNHibernate.TestAssociation.OneToOne
{
    
/// <summary>
    
///    
    
/// </summary>

    [Serializable]
    
public class Employee
    
{
        
Private Members

        
Default ( Empty ) Class Constuctor // End of Default ( Empty ) Class Constuctor

        
Public Properties

        
Public Functions

        
Equals And HashCode Overrides
    }

}

1.3 示例映射文件

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
    
<class name="DDLLY.TestNHibernate.TestAssociation.OneToOne.Person,DDLLY.TestNHibernate.TestAssociation" table="T_Person">

        
<id name="PersonId" column="PersonId" type="Int32" unsaved-value="0">
            
<generator class="native"/>
        
</id>
        
<property column="Name" type="String" name="Name" length="64" />

    
<one-to-one name="Employee" class="DDLLY.TestNHibernate.TestAssociation.OneToOne.Employee,DDLLY.TestNHibernate.TestAssociation" cascade="all"></one-to-one>
        
    
</class>
</hibernate-mapping>

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
    
<class name="DDLLY.TestNHibernate.TestAssociation.OneToOne.Employee,DDLLY.TestNHibernate.TestAssociation" table="T_Employee">

        
<id name="PersonId" column="PersonId" type="Int32" unsaved-value="0">
      
<generator class="foreign">
        
<param name="property">Person</param>
      
</generator>
        
</id>
        
<property column="Job" type="String" name="Job" length="64" />

    
<one-to-one name="Person" class="DDLLY.TestNHibernate.TestAssociation.OneToOne.Person,DDLLY.TestNHibernate.TestAssociation" constrained="true"></one-to-one>
        
    
</class>
</hibernate-mapping>

1.4 说明

constrained(约束): 表明该类对应的表对应的数据库表,和被关联的对象所对应的数据库表之间,通过一个外键引用对主键进行约束。这个选项影响Save()和Delete()在级联执行时的先后顺序(也在schema export tool中被使用)。

property-ref: (可选) 指定关联类的一个属性,这个属性将会和本外键相对应。如果没有指定,会使用对方关联类的主键。

<generator class="foreign">:表示使用另外一个相关联的对象的标识符,来创建主健。T_Employee的PersonId来自T_Person的ParentId。

Employee依赖于Person,所以通常在Person设置cascade。

2.另一种one-to-one

2.1数据库表结构

其中T_Person1为主表,T_Employee1为子表。T_Employee1的PersonId设置唯一约束,参照T_Person1的PersonId。

2.2示例映射类文件

/*
/*作者:DDL
/*联系:
http://renrenqq.cnblogs.com/
*/


using System;

namespace DDLLY.TestNHibernate.TestAssociation.OneToOne1
{
    
/// <summary>
    
///    
    
/// </summary>

    [Serializable]
    
public class Person
    
{
        
Private Members

        
Default ( Empty ) Class Constuctor // End of Default ( Empty ) Class Constuctor

        
Public Properties

        
Public Functions

        
Equals And HashCode Overrides
    }

}

 

/*
/*作者:DDL
/*联系:
http://renrenqq.cnblogs.com/
*/


using System;

namespace DDLLY.TestNHibernate.TestAssociation.OneToOne1
{
    
/// <summary>
    
///    
    
/// </summary>

    [Serializable]
    
public class Employee
    
{
        
Private Members

        
Default ( Empty ) Class Constuctor // End of Default ( Empty ) Class Constuctor

        
Public Properties

        
Public Functions

        
Equals And HashCode Overrides
    }

}


2.3示例映射文件

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
    
<class name="DDLLY.TestNHibernate.TestAssociation.OneToOne1.Person,DDLLY.TestNHibernate.TestAssociation" table="T_Person1">

        
<id name="PersonId" column="PersonId" type="Int32" unsaved-value="0">
            
<generator class="native"/>
        
</id>
        
<property column="Name" type="String" name="Name" length="64" />

    
<one-to-one name="Employee" class="DDLLY.TestNHibernate.TestAssociation.OneToOne1.Employee,DDLLY.TestNHibernate.TestAssociation" cascade="all"></one-to-one>
        
    
</class>
</hibernate-mapping>


<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
    
<class name="DDLLY.TestNHibernate.TestAssociation.OneToOne1.Employee,DDLLY.TestNHibernate.TestAssociation" table="T_Employee1">

        
<id name="EmployeeId" column="EmployeeId" type="Int32" unsaved-value="0">
      
<generator class="native"/>
    
</id>
    
<property column="Job" type="String" name="Job" length="64" />

    
<many-to-one name="Person" class="DDLLY.TestNHibernate.TestAssociation.OneToOne1.Person,DDLLY.TestNHibernate.TestAssociation" column="PersonId"  unique="true"></many-to-one>
        
    
</class>
</hibernate-mapping>

2.4说明

这种one-to-one实际上是一种特殊的one-to-many,如果T_Employee1的PersonId不设置唯一约束,则可成为one-to-many。所以在T_Employee端设置many-to-one而不是one-to-one,记住要加上unique="true"表示唯一约束。

3.one-to-many

3.1 数据库表结构

T_Parent为主表,T_Child的ParentId参照T_Parent的ParentId。

注意:对于单向的one-to-many映射,cascade过程中会用到把T_Child表的ParentId设置为Null,所以ParentId应设为允许NULL;

而双向one-to-many映射,建议把T_Child的ParentI设置为不允许NULL

3.2 示例映射类文件(单向)

/*
/*作者:DDL
/*联系:
http://renrenqq.cnblogs.com/
*/


using System;
using System.Collections;

namespace DDLLY.TestNHibernate.TestAssociation.OneToMany1
{
    
/// <summary>
    
///    
    
/// </summary>

    [Serializable]
    
public class Parent
    
{
        
Private Members

        
Default ( Empty ) Class Constuctor // End of Default ( Empty ) Class Constuctor

        
Public Properties

        
Public Functions

        
Equals And HashCode Overrides
    }

}

/*
/*作者:DDL
/*联系:
http://renrenqq.cnblogs.com/
*/


using System;

namespace DDLLY.TestNHibernate.TestAssociation.OneToMany1
{
    
/// <summary>
    
///    
    
/// </summary>

    [Serializable]
    
public class Child
    
{
        
Private Members

        
Default ( Empty ) Class Constuctor // End of Default ( Empty ) Class Constuctor

        
Public Properties 

        
Public Functions

        
Equals And HashCode Overrides
    }

}

3.3 示例映射文件(单向)

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
    
<class name="DDLLY.TestNHibernate.TestAssociation.OneToMany1.Parent,DDLLY.TestNHibernate.TestAssociation" table="T_Parent">

        
<id name="ParentId" column="ParentId" type="Int32" unsaved-value="0">
            
<generator class="native"/>
        
</id>
        
<property column="Name" type="String" name="Name" length="64" />
    
    
<bag name="Children" cascade="all"  lazy="true">
      
<key column="ParentId"/>
      
<one-to-many class="DDLLY.TestNHibernate.TestAssociation.OneToMany1.Child,DDLLY.TestNHibernate.TestAssociation"/>
    
</bag>        
    
    
</class>
</hibernate-mapping>

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
    
<class name="DDLLY.TestNHibernate.TestAssociation.OneToMany1.Child,DDLLY.TestNHibernate.TestAssociation" table="T_Child">

        
<id name="ChildId" column="ChildId" type="Int32" unsaved-value="0">
            
<generator class="native"/>
        
</id>
        
<property column="Name" type="String" name="Name" length="64" />
    
<property column="ParentId" type="Int32" name="ParentId"/>
        
    
</class>
</hibernate-mapping>

3.4 示例映射类文件(双向)

/*
/*作者:DDL
/*联系:
http://renrenqq.cnblogs.com/
*/


using System;
using System.Collections;

namespace DDLLY.TestNHibernate.TestAssociation.OneToMany
{
    
/// <summary>
    
///    
    
/// </summary>

    [Serializable]
    
public class Parent
    
{
        
Private Members

        
Default ( Empty ) Class Constuctor // End of Default ( Empty ) Class Constuctor

        
Public Properties

        
Public Functions

        
Equals And HashCode Overrides
    }

}

/*
/*作者:DDL
/*联系:
http://renrenqq.cnblogs.com/
*/


using System;

namespace DDLLY.TestNHibernate.TestAssociation.OneToMany
{
    
/// <summary>
    
///    
    
/// </summary>

    [Serializable]
    
public class Child
    
{
        
Private Members

        
Default ( Empty ) Class Constuctor // End of Default ( Empty ) Class Constuctor

        
Public Properties 

        
Public Functions

        
Equals And HashCode Overrides
    }

}

3.5 示例映射类文件(双向)

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
    
<class name="DDLLY.TestNHibernate.TestAssociation.OneToMany.Parent,DDLLY.TestNHibernate.TestAssociation" table="T_Parent">

        
<id name="ParentId" column="ParentId" type="Int32" unsaved-value="0">
            
<generator class="native"/>
        
</id>
        
<property column="Name" type="String" name="Name" length="64" />
    
    
<bag name="Children" cascade="all" inverse="true" lazy="true">
      
<key column="ParentId"/>
      
<one-to-many class="DDLLY.TestNHibernate.TestAssociation.OneToMany.Child,DDLLY.TestNHibernate.TestAssociation"/>
    
</bag>        
    
    
</class>
</hibernate-mapping>

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
    
<class name="DDLLY.TestNHibernate.TestAssociation.OneToMany.Child,DDLLY.TestNHibernate.TestAssociation" table="T_Child">

        
<id name="ChildId" column="ChildId" type="Int32" unsaved-value="0">
            
<generator class="native"/>
        
</id>
        
<property column="Name" type="String" name="Name" length="64" />
    
        
<many-to-one name="Parent" column="ParentId" class="DDLLY.TestNHibernate.TestAssociation.OneToMany.Parent,DDLLY.TestNHibernate.TestAssociation" />
        
    
</class>
</hibernate-mapping>

3.6 说明

在NHibernate配置文件中使用<set>, <list>, <map>, <bag>, <array> 和 <primitive-array>等元素来定义集合。<bag>是典型的一个,代码中我们用IList和它对应。我们以后会详细讲集合这个话题。

lazy表示允许延迟加载。表示在需要使用时才加载需要的数据。例如使用lazy时我们Load一个Parent他的Children为空,只有我们访问它的某一个Child时数据才会被加载;而不设置lazy我们Load一个Parent时其Children将同时加载。注意:使用lazy加载必须保证对应ISession的打开,否则懒加载会失败。

one-to-many可以设置单向和双向映射,设置单向时Child一段不设置many-to-one,而设置了ParentId的属性。

双向映射需要设置inverse而单向不需要。

单项映射在cascade时会对把T_Child的ParentId使用Update为Null的操作。

建议尽量使用双向映射。

4.many-to-many

4.1 数据库表结构

4.2 示例映射类文件

/*
/*作者:DDL
/*联系:
http://renrenqq.cnblogs.com/
*/


using System;
using System.Collections;

namespace DDLLY.TestNHibernate.TestAssociation.ManyToMany
{
    
/// <summary>
    
///    
    
/// </summary>

    [Serializable]
    
public class User
    
{
        
Private Members

        
Default ( Empty ) Class Constuctor // End of Default ( Empty ) Class Constuctor

        
Public Properties

        
Public Functions

        
Equals And HashCode Overrides
    }

}

/*
/*作者:DDL
/*联系:
http://renrenqq.cnblogs.com/
*/


using System;
using System.Collections;

namespace DDLLY.TestNHibernate.TestAssociation.ManyToMany
{
    
/// <summary>
    
///    
    
/// </summary>

    [Serializable]
    
public class Role
    
{
        
Private Members

        
Default ( Empty ) Class Constuctor // End of Default ( Empty ) Class Constuctor

        
Public Properties

        
Public Functions

        
Equals And HashCode Overrides
    }

}

4.3 示例映射文件

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
    
<class name="DDLLY.TestNHibernate.TestAssociation.ManyToMany.User,DDLLY.TestNHibernate.TestAssociation" table="T_User">

        
<id name="UserId" column="UserId" type="Int32" unsaved-value="0">
            
<generator class="native"/>
        
</id>
        
<property column="UserName" type="String" name="UserName" not-null="true" length="64" />
        
<property column="Password" type="String" name="Password" not-null="true" length="32" />
        
<property column="Email" type="String" name="Email" length="64" />

    
<bag name="Roles" table="T_User_Role" lazy="true">
      
<key column="UserId"/>
      
<many-to-many class="DDLLY.TestNHibernate.TestAssociation.ManyToMany.Role,DDLLY.TestNHibernate.TestAssociation" column="RoleId"/>
    
</bag>
        
    
</class>
</hibernate-mapping>

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
    
<class name="DDLLY.TestNHibernate.TestAssociation.ManyToMany.Role,DDLLY.TestNHibernate.TestAssociation" table="T_Role">

        
<id name="RoleId" column="RoleId" type="Int32" unsaved-value="0">
            
<generator class="native"/>
        
</id>
        
<property column="RoleName" type="String" name="RoleName" not-null="true" length="64" />

    
<bag name="Users" table="T_User_Role" lazy="true" inverse="true">
      
<key column="RoleId"/>
      
<many-to-many class="DDLLY.TestNHibernate.TestAssociation.ManyToMany.User,DDLLY.TestNHibernate.TestAssociation" column="UserId"/>
    
</bag>


  
</class>
</hibernate-mapping>

4.4 说明

many-to-many性能不佳,数据量大时应尽可能避免使用。并尽可能使用lazy="true"。

在数据量少的一端设置inverse="true",让数据量多的一段维护cascade。

二、cascade分析

1.总述

cascade:(默认为none)级联。指明哪些操作会从对象级联到关联的对象。

orphans:孤儿,没有夫对象的子对象。对于代码Child.Parent==null,对于数据库T_Child表中ParentId为Null的数据。

delete orphans表示cascade时删除孤儿。

一般系统中是不允许孤儿存在的,我们可以通过数据库的约束来限制孤儿,例如T_Child的ParentId设为Not NULL。

如果确实存在孤儿请考虑适合的cascade策略。

cascade类型 对应操作

all

Save / Delete / Update

all-delete-orphan

Save / Delete / Update + delete orphans

delete-orphan

Delete + delete orphans

none

No Cascades

delete

Delete

save-update

Save / Update

 2.one-to-one

a.初始化数据

PersonId Name Job
1 DDL 编程
2 LLY NULL

b.测试方法

TestAddPersonWithAddEmployee

Person person = new Person();
person.Name 
= "newPerson";
Employee employee 
= new Employee();
employee.Job 
= "newJob";
person.Employee 
= employee;
employee.Person 
= person;

session.Save(person);

TestUpdatePersonWithAddEmployee

Person person = session.Load(typeof (Person), 2as Person;
person.Employee 
= new Employee();
person.Employee.Person 
= person;
person.Employee.Job 
= "LLYJob";

session.Update(person);

TestUpdatePersonWithUpdateEmployee

Person person = session.Load(typeof (Person), 1as Person;
person.Employee.Job 
= "DDL'New Job";

session.Update(person);

TestDeletePersonWithDeleteEmployee

Person person = session.Load(typeof (Person), 1as Person;

session.Delete(person);

c.测试结果

测试方法

save-update

delete

delete-orphan

all

all-delete-orphan

none

TestAddPersonWithAddEmployee

Y

N

N

Y

Y

N

TestUpdatePersonWithAddEmployee

Y

N

N

Y

Y

N

TestUpdatePersonWithUpdateEmployee

Y

Y

Y

Y

Y

Y

TestDeletePersonWithDeleteEmployee

N

Y

Y

Y

Y

N

 2.另一种one-to-one

a.初始化数据

PersonId Name EmployeeId Job
1 DDL 1 编程
2 LLY NULL NULL

 b.测试方法

TestAddPersonWithAddEmployee

不支持

TestUpdatePersonWithAddEmployee

Person person = session.Load(typeof (Person), 2as Person;
person.Employee 
= new Employee();
person.Employee.Person 
= person;
person.Employee.Job 
= "LLYJob";

session.Update(person);
session.Flush();

TestUpdatePersonWithUpdateEmployee

Person person = session.Load(typeof (Person), 1as Person;
person.Employee.Job 
= "DDL'New Job";

session.Update(person);
session.Flush();

 TestDeletePersonWithDeleteEmployee

Person person = session.Load(typeof (Person), 1as Person;

session.Delete(person);
session.Flush();

c.测试结果

测试方法

save-update

delete

delete-orphan

all

all-delete-orphan

none

TestAddPersonWithAddEmployee

不支持

不支持

不支持

不支持

不支持

不支持

TestUpdatePersonWithAddEmployee

Y

N

N

Y

Y

N

TestUpdatePersonWithUpdateEmployee

Y

Y

Y

Y

Y

Y

TestDeletePersonWithDeleteEmployee

N

Y

Y

Y

Y

N

3.one-to-many(双向)

a.初始化数据

ParentId ParentName ChildId ChildName
1 Parent1 1 Child1
2 Parent2 NULL NULL

b.测试方法

TestAddParentWithAddChild

Parent parent = new Parent();
parent.Name 
= "NewParent";

Child child 
= new Child();
child.Name 
= "NewChild";
child.Parent 
= parent;

parent.Children.Add(child);

session.Save(parent);
session.Flush();

TestUpdateParentWithAddChild

Parent parent = session.Load(typeof (Parent), 2as Parent;

Child child 
= new Child();
child.Name 
= "NewChild";
child.Parent 
= parent;

parent.Children.Add(child);

session.Update(parent);

session.Flush();

TestUpdateParentWithUpdateChild

Parent parent = session.Load(typeof (Parent), 1as Parent;

Child child 
= (Child) parent.Children[0];

child.Name 
= "UpdateName";

session.Update(parent);

session.Flush();

TestDeleteParentWithChild

Parent parent = session.Load(typeof (Parent), 1as Parent;

session.Delete(parent);
session.Flush();

 c.测试结果

测试方法

save-update

delete

delete-orphan

all

all-delete-orphan

none

TestAddParentWithAddChild Y N N Y Y N
TestUpdateParentWithAddChild Y N N Y Y N
TestUpdateParentWithUpdateChild Y Y Y Y Y Y
TestDeleteParentWithChild N Y Y Y Y N

4.one-to-many(单向)

a.初始化数据

同上

b.测试方法

TestAddParentWithAddChild

不支持

TestUpdateParentWithAddChild

Parent parent = session.Load(typeof (Parent), 2as Parent;

Child child 
= new Child();
child.Name 
= "NewChild";
child.ParentId 
= parent.ParentId;

parent.Children.Add(child);

session.Update(parent);

session.Flush();

TestUpdateParentWithUpdateChild

Parent parent = session.Load(typeof (Parent), 1as Parent;

Child child 
= (Child) parent.Children[0];

child.Name 
= "UpdateName";

session.Update(parent);

session.Flush();

TestDeleteParentWithChild

Parent parent = session.Load(typeof (Parent), 1as Parent;

session.Delete(parent);

session.Flush();

 c.测试结果

测试方法

save-update

delete

delete-orphan

all

all-delete-orphan

none

TestAddParentWithAddChild 不支持 不支持 不支持 不支持 不支持 不支持
TestUpdateParentWithAddChild Y N N Y Y N
TestUpdateParentWithUpdateChild Y Y Y Y Y Y
TestDeleteParentWithChild Parent被删除,Child成为孤儿 Y Y Y Y Parent被删除,Child成为孤儿

5.many-to-many
many-to-many和别的关联映射有所不同。例子中:Role和User没有直接的依赖关系,而是通过一张中间表完成。在删除User时一般不会要求删除Role,而是删除之间的关系(即从中间表删除数据)。

a.初始化数据

UserId UserName Password Email RoleId RoleName
1 DDL 1 NULL 1 角色1
1 DDL 1 NULL 2 角色2
2 LLY 2 NULL 1 角色1
3 陌生人 3 NULL NULL NULL
NULL NULL NULL NULL 3 角色3

b.测试方法

TestAddRoleToUser

User user = session.Load(typeof (User), 1as User;
Role role 
= session.Load(typeof (Role), 3as Role;

user.Roles.Add(role);
role.Users.Add(user);

session.Update(user);
session.Flush();

 TestRemoveRoleFromUser

User user = session.Load(typeof (User), 1as User;
Role role 
= session.Load(typeof (Role), 2as Role;

user.Roles.Remove(role);
role.Users.Remove(user);

session.Update(user);
session.Flush();

 

 TestUpdateUserWithRole

User user = session.Load(typeof(User), 2as User;
((Role) user.Roles[
0]).RoleName = "UpdateRole";

session.Update(user);
session.Flush();

TestDeleteUserWithSetRole

User user = session.Load(typeof (User), 1as User;
session.Delete(user);
session.Flush();

c.测试结果

测试方法

save-update

delete

delete-orphan

all

all-delete-orphan

none

TestAddRoleToUser Y Y Y Y Y Y
TestRemoveRoleFromUser Y Y Y Y Y Y
TestUpdateUserWithRole Y Y Y Y Y Y
TestDeleteUserWithSetRole N Uer被删除,但和其有关的Role也被删除 Uer被删除,但和其有关的Role也被删除 Uer被删除,但和其有关的Role也被删除 Uer被删除,但和其有关的Role也被删除 N

 三、结论

关联是NHibernate里面功能很强的一块,但也使很容易滥用而造成引起性能或其他问题的地方。所以请慎重的使用。

在使用之前,请考虑好以下问题:

1.关系分析,一对多,多对多,还是一对一。

2.确定依赖关系,例如:Child依赖于Parent。

3.是否允许存在孤儿,例如:存在Child没有Parent(即在数据库中ParentId为Null的Child)。

4.在对等的关系中是否有主动端。例如:需要给Parent设置Child还是给Child找Parent,或者两边都可以操作。

5.关联两端可能出现的数据量以及在页面显示时是否分页。如果数据量大或者页面上需要分页显示,建议不要采用关联映射。如果数据量大,性能会不好,如果需要分页,关联所有数据似乎没有什么意思。

6.页面上可能的对象操作方法。例如:先读取一个Parent,然后添加Child,然后保存。

请根据你的情况设置关联映射,而对于cascade标准的设置可以满足绝大多数的需要,如一有特殊情况,请按照上面的分析选择合适的。

下载代码 

0
0
(请您对文章做出评价)
« 上一篇:特里当选英格兰队新任队长
» 下一篇:请帮'Atlas'起个名字
posted on 2006-08-16 14:51 DDL 阅读(10740) 评论(22)  编辑 收藏 网摘 所属分类: NHibernate

评论:
#1楼 2006-08-16 17:00 | junmy      
Good....

新手很有用.

  回复  引用  查看    
#2楼 2006-08-16 21:07 | 双鱼座      
1-to-n和n-to-n是没有问题的。事实上1-to-1会有问题。因为,根本上Employee就应该自Person派生,除了级联删除以外,还有更多的地方希望操作Employee的时候自动操作Person。如果Employee和Customer分别从Person派生,如果我希望查找所有生日在某一天的Person,你通过什么依据去寻找Person来自哪些实体?
  回复  引用  查看    
#3楼[楼主] 2006-08-17 09:48 | DDL      
实际上我感觉one-to-one(包括1-to-n和n-to-n)不是用来表示派生关系的东东,而是表示关联的。
感觉用User或者Address表示这种关系更加的恰当.

User,Address间不是继承的关系,而是Address是User的一部分.

用Person和Employee确实容易让人从名称而感觉到是继承关系,但这个例子已经是一个经典的范例了(很多NHibernate的书籍都在使用).所以我也沿用了这个范例.个人感觉Employee名称改为Job比较合适.

  回复  引用  查看    
#4楼 2006-08-17 10:12 | 双鱼座      
1-to-1是不是用来表示继承的先不讨论,继承是通过1-to-1来表示是不用怀疑的。我没有研究过NHibernate,不过我大略研究过Hibernate,那个RedSaga示例就是用1-to-1表示继承。
我比较质疑你使用“经典”这个词的准确性。当然,这也是见仁见智的。

  回复  引用  查看    
#5楼[楼主] 2006-08-17 10:27 | DDL      
@双鱼座
对经典这个词也是打上引号的.加上这个词是因为看到很多这样例子的无奈.
你讲的RedSaga的例子是指哪个?
是那个论坛吗?
我回去看看,下周我也会把NHibernate中继承的做法写个blog.

很有兴趣和你继续谈论下去.

  回复  引用  查看    
#6楼 2006-08-17 10:59 | 双鱼座      
@DDL
我的Java相当烂,所以只能看一些简单的资料。《深入浅出Hibernate》就比较浅,RedSaga示例这一章是曹晓钢写的,他曾经是我在大富翁论坛(http://www.delphibbs.com.delphibbs)里的大佬,个人比较认可他是可能是因为相同的Delphi背景,所以比较欣赏他的思考方式。
BTW:你的文章也非常优秀,看得出来,在很多方面你的研究比较独到,值得学习。

  回复  引用  查看    
#7楼[楼主] 2006-08-17 12:25 | DDL      
我看过你的关于Kanas.Net框架的一些背景,不由得让我肃然起敬。
 
你在写程序的时候我还是完全是个门外汉,所以会觉得自己是不是有资格和能力同你争论技术,我是抱着学习的态度发表自己的个人观点。
 
我写的东西不敢说优秀,只是写了些基本的东西,更谈不少学习了。
 
还有我和你同样不是计算机专业的。

  回复  引用  查看    
#8楼 2006-08-18 08:12 | 阳春三月      
好文,以前自己也研究过,但没有总结出这么有条理的文章。对学习非常有用,谢谢!
  回复  引用  查看    
#9楼 2006-08-22 16:11 | Elite      
好东西。毕业设计就是因为有涉及到多对多的关系,没写完整,成为唯一的缺陷。
  回复  引用  查看    
#10楼 2006-11-08 14:56 | netx[未注册用户]
代码下不了.....................
  回复  引用    
#11楼 2006-11-22 16:34 | Teng[未注册用户]
费了牛大的劲才找到这么一片好文章,代表党和人民谢谢LZ了!
  回复  引用    
#12楼 2006-11-22 16:34 | Teng[未注册用户]
费了牛大的劲才找到这么一片好文章,代表党和人民谢谢LZ了!
  回复  引用    
#13楼 2006-12-23 16:33 | jack[匿名][未注册用户]
好文!先谢谢了。
我有个问题,就是在第一种one to one关联中,一个employee关联到一个person,现在我只需要delete employee保留person,我该怎么做呢?谢谢!

  回复  引用    
#14楼 2007-03-10 17:24 | 虫虫[未注册用户]
如果 many-to-many关系
T_Parent_Child 表中还有其他字段,
应该怎么做呢?

  回复  引用    
#15楼 2007-07-09 16:11 | 无阻[未注册用户]
在使用one-to-many(单向)时,出下一下异常:

未处理 NHibernate.LazyInitializationException
Message="Failed to lazily initialize a collection"
Source="NHibernate"
StackTrace:
在 NHibernate.Collection.AbstractPersistentCollection.Initialize(Boolean writing)
在 NHibernate.Collection.AbstractPersistentCollection.Read()
在 NHibernate.Collection.PersistentBag.get_Item(Int32 index)
在 NHibernateTest.Program.OneToMany() 位置 G:\Design\NHibernateTest\NHibernateTest\Program.cs:行号 90
在 NHibernateTest.Program.Main(String[] args) 位置 G:\Design\NHibernateTest\NHibernateTest\Program.cs:行号 21
在 System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args)
在 System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
在 Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
在 System.Threading.ThreadHelper.ThreadStart_Context(Object state)
在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
在 System.Threading.ThreadHelper.ThreadStart()

  回复  引用    
#16楼 2007-07-18 22:54 | 李[未注册用户]
你好,代码不能下载.
  回复  引用    
#17楼 2007-11-26 10:48 | ....      
请问一个问题,当我设置 user 一端inverse="false"时,删除User会自动的删除关联表User_Role的数据,但是删除Role时我也想让它自动删除关联表User_Role的数据,该怎么办,有什么优雅点的解决方案没有?


我现在是通过设置外键关联来删除。

  回复  引用  查看    
#18楼 2008-11-18 02:50 | EricWen      
写得很好!

  回复  引用  查看    
#19楼 2009-05-13 09:50 | piaowufeiyang_1[未注册用户]
在one-to-many(双向)这里有一些疑问:
在使用tAddParentWithAddChild方法时,出现
Unexpected row count: 0; expected: 1的异常,
主表加进去了 但是 子表没有加进去,而且在inverse="true"中应该是子表维护关系吧? 期待您的答复!

  回复  引用    
#20楼 2009-05-13 09:53 | piaowufeiyang_1[未注册用户]
在使用tAddParentWithAddChild方法时,可以在
主表加进去,但是可以更新子表中有的字段,这个不太清楚了
希望能进行交流下~~~!

  回复  引用    
#21楼 2010-01-05 14:46 | 蓝天_白云      
非常好的入门资料 学习了

  回复  引用  查看    
#22楼 2010-01-05 14:47 | 蓝天_白云      
另外代码不能下载

  回复  引用  查看