1

期待 Nhibernate 用户、专业人士、专家和开发人员。请帮忙 !!!

我想实现两个类之间的:m 关系。一个学生参加更多的课程,一个课程由更多的学生组成。我使用包进行多对多双向关联,以从每个站点获取两个列表。

两个学生和课程类:

public class Student {         
     // Attributes........

     [XmlIgnore]
     public virtual IList MyCourses { get; set; }

     // Add Method
     public virtual void AddCourse(Course c)
    {
        if (MyCourses == null)
            MyCourses = new List<Course>();

        if (!MyCourses.Contains(c))
            MyCourses.Add(c);

        if (c.Members== null)
            c.Members= new List<Student>();

        if (!c.Members.Contains(this))
            c.Members.Add(this);
    }

    public virtual void RemoveCourse(Course c)
    {
        if (MyCourses != null)
            MyCourses.Remove(c);

        if (c.Members!= null)
            c.Members.Remove(this);
    }
}

public class Course {         
     // Attributes........

     [XmlIgnore]
     public virtual IList Members { get; set; }
}

在数据库中有两个表 t_Student、t_Course 和一个关系表 tr_StudentCourse(id, student_id, course_id)。

<class name="Student" table="t_Student" polymorphism="explicit">
 ..... 
 <bag name="MyCourses" table="tr_StudentCourse">
   <key column="student_id" />
   <many-to-many class="Course" column="course_id" not-found="ignore" />
 </bag>    
</class>

<class name="Course" table="t_Course" polymorphism="explicit">
 ..... 
 <bag name="Members" table="tr_StudentCourse" inverse="true">
   <key column="course_id" />
   <many-to-many class="Student" column="student_id" not-found="ignore" />
 </bag>    
</class>

在双向关联中,课程被选为反向。我做了与 nhibernate 文档第 6.8 节中的示例 (Categorie, Item) 相同的操作。因此,我通过调用添加/删除方法在 MyCourses 列表中插入课程后保存了学生对象。

Student st1 = new Student();
Course c1 = new Course();    
Course c2 = new Course();
st1.AddCourse(c1);
st1.AddCourse(c2);
session.saveOrUpdate(st1);

效果很好,可以在数据库中找到 st1、c1 及其关系 (st1,c1)。关系数据集是 (id= 1 , st1.id, c1.id) 和 (id= 2 , st1.id, c2.id)。然后我向对象 st1 添加更多课程。

Course c3 = new Course();
st1.AddCourse(c3);
session.saveOrUpdate(st1);

我可以看到 3 个关系数据集,但是删除了两个旧关系,并使用另一个新 id 创建了新的三个。(id= 3 , st1.id, c1.id), (id= 4 , st1.id, c2.id) 和 (id= 5 , st1.id, c3.id)。关系表中没有 id=1 和 2 的数据集。

如果我从 student.MyCourse 中删除课程然后保存学生对象,则删除相同。所有集合也被删除并重新创建了一个新列表,其中少了一个已删除元素。这个问题使得关系表中的 id 的创建速度非常快,并且通过对关系进行备份而产生了麻烦。

我在互联网、文档和论坛中查看了几天,以找出为什么整个旧集合被删除以及每次更改都创建了一个新集合,但我没有成功。这是来自休眠映射的错误还是我做错了什么?

我非常感谢您的帮助和回答。

Nhibernate 文档http://nhforge.org/doc/nh/en/index.htm

4

2 回答 2

2

NHibernate 不能单独创建、删除或更新行,因为没有可用于标识单个行的键。

通过“6.2. 映射集合”中的注释

一旦您id进入,tr_StudentCourse您可以尝试使用索引集合,即替换<bag><map>或类似并将<index>元素添加到映射中:

<index
    column="id"
    type="int"
/>

甚至为关系表创建一个特殊实体以与<index-many-to-many>.

于 2010-01-07T11:56:27.247 回答
1

这是我在 NHibernate 网站上找到的:

Hibernate 正在删除我的整个集合并重新创建它,而不是更新表。

这通常发生在 NHibernate 无法确定集合中更改了哪些项目时。常见原因有:

  • 用一个新的集合实例完全替换一个持久化集合,传递 NHibernate 一个手动构造的对象并在其上调用 Update。

  • 序列化/反序列化持久化集合显然也会导致这个问题。

    • 使用 inverse="false" 更新 a - 在这种情况下,NHibernate 无法构造 SQL 来更新单个集合项。

因此,为避免该问题:

将您从 NHibernate 获得的同一个集合实例传回给它(不一定在同一个会话中),尝试使用其他集合而不是<bag>(<idbag><set>),或者尝试使用 inverse="true" 属性<bag>

于 2010-01-08T08:35:34.960 回答