NHibernate: коллекция «многие ко многим» - PullRequest
1 голос
/ 19 августа 2011

У клиента может быть несколько контактов. Код ниже работает, но ... контакты для этого клиента сначала удаляются, а после вставляются снова. Не возможно избежать этого удаления и просто вставить новое?

<class name="Customer" table="Customer">
    <id name="Id">
        <generator class="native" />
    </id>
    <property name="LastName" not-null="true" />

    <bag name="Contacts" cascade="all-delete-orphan" table="CustomerContact">
        <key column="Customer" not-null="true" />
        <many-to-many class="Contact"/>
    </bag>l
</class>

<class name="Contact" table="Contact">
    <id name="Id">
      <generator class="native" />
    </id>
    <property name="LastName" not-null="true" />

    <many-to-one name="Customer" column="Customer" not-null="true" />
</class>

public virtual void AddContact(Contact contact)
{
    Contacts.Add(contact);
    contact.Customer = this;
}

Когда я делаю этот код дважды, чтобы добавить 2 контакта:

Contact contact = new Contact() { LastName = "MyLastName" };
Customer customer = session.Get(customerId);
customer.AddContact(contact);
session.Update(customer);

enter image description here

Ответы [ 2 ]

2 голосов
/ 19 августа 2011

Вы используете bag для своей коллекции, сумка может содержать дубликаты, не поддерживает порядок и нет способа четко идентифицировать отдельную запись в сумке с помощью SQL.NH удаляет и вставляет все назначенные объекты.Вместо этого используйте set, если оно соответствует вашим требованиям.

1 голос
/ 19 августа 2011

Обычно это происходит, когда NH потерял постоянную информацию о коллекции. Предполагается, что вы изменили всю коллекцию. Для эффективного обновления базы данных она удаляет все элементы в одном запросе (удалить ..., где customer = 5) и вставляет новые элементы.

Вы, вероятно, не возвращаете коллекцию, предоставленную NH.

Типичная ошибка:

  IList<Contact> Contacts
  {
    get { return contacts; }
    // wrong: creates a new List and replaces the NH persistent collection
    set { contacts = value.ToList(); }
  }

Кстати, вы должны сделать коллекцию обратной, поскольку это избыточность для контакта. Отношение к клиенту:

<bag name="Contacts" cascade="all-delete-orphan" table="CustomerContact" inverse="true">
    <key column="Customer" not-null="true" />
    <many-to-many class="Contact"/>
</bag>
...