2010-01-07 2 views
1

Ожидаются пользователи, профессионалы, гуру и разработчики Nhibernate. Пожалуйста помоги !!!nhibernate mapping many-to-many: почему все коллекции пакетов были удалены и повторно вставлены?

Я хочу реализовать отношение n: 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 (идентификатор, 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> 

курс был выбран в качестве обратного в двунаправленной ассоциации. Я сделал то же, что и пример (Categorie, Item) в разделе 6.8 документации nhibernate. Поэтому я сохранил объект-ученик после вставки курса в список MyCourses, вызвав метод Add/Remove-method.

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 = , st1.id, c1.id) и (id = , st1.id, c2.id). Затем я добавляю дополнительные курсы к объекту st1.

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

Я вижу 3 Relation наборов данных, но эти две старые отношения были удалены и новые три были созданы с другим новым идентификатором. (id = , st1.id, c1.id), (id = , st1.id, c2.id) и (id = , st1.id, c3.id). Нет данных с идентификатором id = 1 и еще 2 в таблице отношений.

То же самое, удалив, если я удалю курс из student.MyCourse, а затем сохраните объект-ученик. Вся коллекция также была удалена и воссоздан новый список, в котором меньше одного удаляемого элемента. Эта проблема приводит к тому, что идентификатор в таблице отношений увеличивается очень быстро и имеет сложность, делая резервную связь.

Я просмотрел несколько дней в Интернете, документации и форумах, чтобы узнать, почему вся старая коллекция была удалена, а новая, созданная каждым изменением, но я не был успешным. Это ошибка от nhibernate mapping или я сделал что-то неправильно?

Я очень благодарен вам за помощь и ответ.

Nhibernate документация http://nhforge.org/doc/nh/en/index.htm

ответ

2

NHibernate не может создавать, удалять или обновлять строки по отдельности, потому что нет ключа, который может быть использован для идентификации отдельную строку.

По note from "6.2. Mapping a Collection"

Как только у вас есть id в tr_StudentCourse вы можете попробовать использовать индексированные коллекции, т.е.заменить <bag> с <map> или аналогичными и добавить <index> элемент отображения:

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

или даже создать специальный орган для таблицы соотношения для использования с <index-many-to-many>.

1

Это то, что я нашел на сайте NHibernate:

Hibernate удаляет всю мою коллекцию и воссоздавать ее вместо обновления таблицы.

Это обычно происходит, когда NHibernate не может определить, какие элементы были изменены в коллекции. Наиболее частые причины являются:

  • заменить постоянную коллекцию полностью с новой коллекцией например, проходящей NHibernate вручную построенный объект и вызывающим Update на нем.

  • Сериализация/десериализация Постоянная коллекция, очевидно, также вызывает эту проблему.

    • обновление с обратным = «ложь» - в этом случае, NHibernate не может построить SQL для обновления отдельного элемента коллекции.

Таким образом, чтобы избежать этой проблемы:

пройти тот же экземпляр коллекции, который вы получили от NHibernate назад к нему (не обязательно в той же сессии), попробовать использовать некоторые другие коллекции вместо <bag> (<idbag> или <set>), или попробуйте использовать атрибут inverse = "true" для <bag>.