NHibernate有一个懒惰的负载

问题描述 投票:1回答:2

我有一个父子关系,在Sql Server上只有一个孩子。孩子包含我不会加载的胖blob数据。子项是可选的,它必须取决于父项的生命周期。所以孩子的外键,指向父母并且是独一无二的。

我可以在Hibernate参考上使用official示例。

public class Phone
{
    public virtual long Id { get; set; }

    public virtual string Number { get; set; }

    public virtual PhoneDetails Details { get; set; }
}

public class PhoneDetails
{
    public virtual int Id { get; set; }

    public virtual Phone Phone { get; set; }

    public virtual string Provider { get; set; }
}

电话详细信息必须取决于数据库上的父生命周期。我可以在sql上使用一对一关系,在子进程上使用唯一外键,或者使用简单外键(如示例中)与唯一约束进行多对一关系。

CREATE TABLE Phone (
    id BIGINT IDENTITY PRIMARY KEY,
    number VARCHAR(255)
)

CREATE TABLE PhoneDetails (
    id BIGINT IDENTITY PRIMARY KEY,
    phone_id BIGINT UNIQUE FOREIGN KEY REFERENCES dbo.Phone(id),
    provider VARCHAR(255)        
)

我认为这很好:

enter image description here

所以我有一个电话,这可以没有细节,当我需要时,我只能添加一个细节来完成我的对象与其他细节,我不想总是加载。

如何在NHibernate 5上映射这些类?似乎我需要以双向方式使用HasOne,但在这种情况下我不能使用延迟加载,因此电话上的每个简单查询都将导致连接并选择细节的所有字段。

我使用详细信息表来存储我90%的时间都不需要的大量元数据,但现在我尝试加载电话的任何地方,查询加载了巨大的细节,这真的很糟糕。

那么我可以通过哪种方式映射这种关系?

父级和包含无用脂肪数据的单个子级。在sql中我认为结构是可以的,因为我不想要更多的孩子,我希望他们住在父母的下面(所以孩子的FK)。

不管怎样这种关系是不可能的,我错在哪里?数据库设计?映射?

这是我使用的映射:

  <class name="Phone" table="Phone">
    <id name="Id">
      <generator class="native"/>
    </id>
    <property name="Number"/>
    <one-to-one name="PhoneDetails" class="PhoneDetails"/>
  </class>

  <class name="PhoneDetails" table="PhoneDetails">
    <id name="Id">
      <generator class="native"/>
    </id>
    <property name="Provider" />
    <many-to-one name="Phone" column="phone_id" unique="true"/>    
  </class>

我还尝试了第二个选项,在关系模型上使用外部\主键(所以我删除了FK并使用与PK \ FK相同的Id),在子项中使用此映射:

   <one-to-one name="Phone" class="Phone" constrained="true" />
hibernate nhibernate fluent-nhibernate lazy-loading nhibernate-mapping
2个回答
0
投票

可查询的一对一无法在不查询关联表的情况下知道它是否存在,因此,为了加载其代理,需要查询关联的表。从那时起,在过去的讨论中已经考虑过要更好地查询整个状态而不仅仅是密钥,因此是急切的负载。 - >您将无法在非强制性的引用上启用延迟加载。至少没有标准解决方案。

如果你希望关系能够延迟加载PhoneDetails,你必须使它成为强制/不可空。

作为替代方案,您可以将PhoneDetails中的属性标记为lazy="true"。因此,只要您加载父实体,就会访问该表并为PhoneDetail对象创建代理,但只有在您访问它们时才会加载标记为lazy="true"的所有属性。请注意,只要您访问其中一个,就会加载所有带lazy="true"的属性


0
投票

根据SO的回答,非强制性一对一关系不支持Lazy-Loading。

那么,为了解决这个问题,为什么不摆脱这种一对一的关系呢?如果您在90%的时间内不需要详细信息,我会考虑删除关系并使用单独的存储库方法,只允许您检索指定PhoneDetailsPhone

继续你的例子,我最终得到这个:

public class Phone
{
    public virtual long Id { get; set; }

    public virtual string Number { get; set; }
}

public class PhoneDetails
{
    public virtual int Id { get; set; }

    public virtual Phone BelongsToPhone { get; set; }

    public virtual string Provider { get; set; }
}

public class PhoneRepository
{
      public Phone GetPhone( long id ){}

      public PhoneDetails GetPhoneDetails( Phone phone ){}
}
© www.soinside.com 2019 - 2024. All rights reserved.