2009-09-21 56 views
3

我遇到了一对多关系的问题。我有以下域类:流利的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; }   
} 

我照着以下post作出的实体基类。我有以下映射定义:以下列方式

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为空。有人能告诉我我做错了什么吗?

+0

http://stackoverflow.com/questions/713637/inverse-attribute-in-nhibernate – 2009-09-21 18:16:20

回答

5

当你有inverse="false"一个持久化集合,然后父对象拥有的关系,任何改变父母的收集将是反映在数据库中。

当您有一个持续集合inverse="true"时,那么子对象拥有该关系,并且对子对父对象的引用的任何更改都将反映在数据库中。

因为您设置了inverse="true",您需要将子对象的引用更改为父对象,以便NHibernate选择它。如果您希望NHibernate在您将子项添加到父项集合中或从父项集合中删除子项时接收关系的更改,则必须在集合上设置inverse="false"

+0

的确,当没有Not.Nullable()并且PatronId可能为null时,它解决了我的问题。如果在我的单元测试中保存安装的情况并非如此,则会出现以下错误: “NHibernate.PropertyValueException:not-null属性引用空值或瞬态值”。 如何克服这个问题? – GUZ 2009-09-21 13:33:30

+0

答案是:你应该总是改变双方的关系。每次设置孩子的父亲引用并将孩子添加到父代的集合中。无论您每次分两步执行此操作,还是您采用某种透明的方式完成此操作,都取决于您。 – yfeldblum 2009-09-21 22:15:28

+0

我明白。我还有一个问题:我使用PersistenceSpecification单元测试映射。在验证映射时,Institution CheckList方法也会抛出NHibernate.PropertyValueException:“非空属性引用null或瞬态值”。如何在需要更改关系的双方时使用PersistenceSpecification? – GUZ 2009-09-22 06:13:30

1

您必须手动设置机构的安装特性,具体而言,

Installation installation = TestHelper.CreateAnonymousInstallation(); 
Institution institution = TestHelper.CreateAnonymousInstitution(); 
institution.Installation = installation; 
installation.Institutions.Add(institution); 
+0

请记住,nh不会自动同步双向关系。 – epitka 2009-09-21 13:02:47

+0

我知道你的解决方案有效。不过,我认为,在正常的双向关系的情况下,NHibernate应该自动执行该操作。有什么方法可以配置解决方案,以便只需要将孩子添加到收藏夹而无需设置父母引用? – GUZ 2009-09-21 13:03:06

+0

是的。不要设置'inverse =“true”'。但是,如果你直接设置孩子对父母的引用,而不是将孩子添加到父母的集合中,NHibernate可能不会修改关系。 – yfeldblum 2009-09-21 13:14:00