Свободный nHibernate: проблема отношения "один ко многим"

У меня проблема с отношениями "один ко многим". У меня есть следующие доменные классы:

public class Installation : Entity<Installation>
{        
    public virtual string Name { get; set; }
    public virtual IList<Institution> Institutions { get; set; }

    public Installation()
    {
        Institutions = new List<Institution>();
    }
}
public class Institution : Entity
{
    public virtual string Name { get; set; }
    public virtual string Address { get; set; }
    public virtual string City { get; set; }
    public virtual Installation Installation { get; set; }        
}

Я создал базовый класс Entity в соответствии со следующим: сообщение. У меня определены следующие сопоставления:

public class InstitutionMapping : ClassMap<Institution> 
{
    public InstitutionMapping()
    {
        WithTable("Institution");
        Id(i => i.Id).GeneratedBy.Guid();
        Map(i => i.Name).Not.Nullable().WithLengthOf(50);
        Map(i => i.Address).Not.Nullable().WithLengthOf(50);
        Map(i => i.City).Not.Nullable().WithLengthOf(50);
        References(i => i.Installation).ColumnName("InstallationId").Not.Nullable().WithForeignKey();
    }
}

public class InstallationMapping : ClassMap<Installation>
{
    public InstallationMapping()
    {
        WithTable("Installation");
        Id(i => i.Id).GeneratedBy.Guid();
        Map(i => i.Name).Not.Nullable().WithLengthOf(50);
        HasMany<Institution>(i => i.Institutions).KeyColumnNames.Add("InstallationId").Inverse().Cascade.All();
    }
}

Я выполняю модульное тестирование, добавляя учреждения в установку следующим образом:

Installation installation = TestHelper.CreateAnonymousInstallation();
installation.Institutions.Add(TestHelper.CreateAnonymousInstitution());
installation.Institutions.Add(TestHelper.CreateAnonymousInstitution());
session.Save(installation);    
session.Flush();
session.Clear();
Installation returnedInstallation = session.Get<Installation>(installation.Id);
Assert.AreEqual(2, returnedInstallation.Institutions.Count);

Я получаю исключение утверждения, потому что возвращенное количество учреждений равно 0. Я проверил в профилировщике SQL, и учреждения сохранены в базе данных, но их InstallationId равен нулю. Может ли кто-нибудь сказать мне, что я делаю не так?


person GUZ    schedule 21.09.2009    source источник
comment
stackoverflow.com/questions/713637/   -  person Mauricio Scheffer    schedule 21.09.2009


Ответы (2)


Если у вас есть постоянная коллекция с inverse="false", тогда родительский объект владеет отношениями, и любые изменения в родительской коллекции будут отражены в базе данных.

Когда у вас есть постоянная коллекция с inverse="true", тогда дочерний объект владеет отношением, и любые изменения ссылки дочернего элемента на родительский будут отражены в базе данных.

Поскольку вы устанавливаете inverse="true", вам нужно будет изменить ссылку дочернего объекта на родительский объект, чтобы NHibernate мог его уловить. Если вы хотите, чтобы NHibernate улавливал изменения в отношениях всякий раз, когда вы добавляете потомков в родительскую коллекцию или удаляете их из родительской коллекции, вы должны установить inverse="false" в коллекции.

person yfeldblum    schedule 21.09.2009
comment
На самом деле это решает мою проблему, когда нет Not.Nullable () и когда PatronId может иметь значение null. Если это не тот случай, когда я сохраняю установку в своем модульном тесте, я получаю следующую ошибку: NHibernate.PropertyValueException: свойство not-null ссылается на нулевое или временное значение. Как побороть эту проблему? - person GUZ; 21.09.2009
comment
Ответ таков: вы всегда должны менять обе стороны отношений. Установите ссылку на родительский элемент дочернего элемента и каждый раз добавляйте его в коллекцию родительского элемента. Делаете ли вы это каждый раз в два шага или создаете какой-то прозрачный способ сделать это за один шаг, зависит от вас. - person yfeldblum; 22.09.2009
comment
Я понимаю. У меня есть еще одна проблема: я тестирую отображение, используя PersistenceSpecification. При проверке сопоставления метод Institution CheckList также выдает исключение NHibernate.PropertyValueException: свойство not-null ссылается на нулевое или временное значение. Как использовать PersistenceSpecification, когда мне нужно изменить обе стороны отношения? - person GUZ; 22.09.2009
comment
Вы можете либо сопоставить родительскую ссылку дочернего элемента как cascade="all" (в дополнение к сопоставлению родительской коллекции дочерних элементов как cascade="all"), либо убедиться, что вы всегда вызываете ISession.Save на родительском элементе перед сбросом сеанса. - person yfeldblum; 22.09.2009

Вы должны вручную установить свойство установки учреждения, в частности,

Installation installation = TestHelper.CreateAnonymousInstallation();
Institution institution = TestHelper.CreateAnonymousInstitution();
institution.Installation = installation;
installation.Institutions.Add(institution);
person Canton    schedule 21.09.2009
comment
Помните, что nh не выполняет автоматическую синхронизацию двунаправленных отношений. - person epitka; 21.09.2009
comment
Я знаю, что ваше решение работает. Однако я подумал, что в случае нормальных двунаправленных отношений NHibernate должен делать это автоматически. Есть ли способ настроить решение таким образом, чтобы в коллекцию нужно было добавлять только дочерние элементы, не устанавливая родительскую ссылку? - person GUZ; 21.09.2009
comment
да. Не устанавливайте inverse="true". Но затем, если вы установите ссылку дочернего элемента на его родительский элемент напрямую вместо добавления дочернего элемента в родительскую коллекцию, NHibernate может не изменить отношения. - person yfeldblum; 21.09.2009