【问题标题】:Fluent nHibernate: one-to-many relationship IssueFluent nHibernate:一对多关系问题
【发布时间】:2012-12-07 15:15:35
【问题描述】:

我遇到了一对多关系的问题。我有以下域类:

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做了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 Profiler 中检查并且机构已保存在数据库中,但它们的 InstallationId 为空。有人能告诉我我做错了什么吗?

【问题讨论】:

标签: c# nhibernate fluent-nhibernate one-to-many


【解决方案1】:

当您有一个带有inverse="false" 的持久集合时,父对象拥有该关系,并且对父集合的任何更改都将反映在数据库中。

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

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

【讨论】:

  • 当没有 Not.Nullable() 并且 PatronId 可能为空时,它确实解决了我的问题。如果在我的单元测试中保存安装时不是这种情况,我会收到以下错误:“NHibernate.PropertyValueException:非空属性引用空值或瞬态值”。如何克服这个问题?
  • 答案是:你应该总是改变关系的双方。每次都设置孩子的父母参考并将孩子添加到父母的集合中。是每次都分两步执行此操作,还是一步构建某种透明的方式,这取决于您。
  • 我明白了。我还有一个问题:我正在使用 PersistenceSpecification 对映射进行单元测试。在验证机构检查清单方法的映射时,还会抛出 NHibernate.PropertyValueException:“非空属性引用空值或瞬态值”。当我需要改变关系的双方时如何使用 PersistenceSpecification?
  • 您可以将子项的父引用映射为cascade="all"(除了将父项的子项集合映射为cascade="all")或确保您始终在会话之前在父项上调用ISession.Save已冲洗。
【解决方案2】:

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

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

【讨论】:

  • 请记住,nh 不会自动同步双向关系。
  • 我知道您的解决方案有效。但是我认为在正常的双向关系的情况下 NHibernate 应该自动执行此操作。有没有办法配置解决方案,只需要将孩子添加到集合中而不设置父母参考?
  • 是的。不要设置inverse="true"。但是,如果您直接设置子项对其父项的引用,而不是将子项添加到父项的集合中,NHibernate 可能不会修改关系。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-16
  • 1970-01-01
  • 2011-07-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多