NHibernate有一个懒惰的负载
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NHibernate有一个懒惰的负载相关的知识,希望对你有一定的参考价值。
我有一个父子关系,在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)
)
我认为这很好:
所以我有一个电话,这可以没有细节,当我需要时,我只能添加一个细节来完成我的对象与其他细节,我不想总是加载。
如何在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" />
可查询的一对一无法在不查询关联表的情况下知道它是否存在,因此,为了加载其代理,需要查询关联的表。从那时起,在过去的讨论中已经考虑过要更好地查询整个状态而不仅仅是密钥,因此是急切的负载。 - >您将无法在非强制性的引用上启用延迟加载。至少没有标准解决方案。
如果你希望关系能够延迟加载PhoneDetails
,你必须使它成为强制/不可空。
作为替代方案,您可以将PhoneDetails
中的属性标记为lazy="true"
。因此,只要您加载父实体,就会访问该表并为PhoneDetail
对象创建代理,但只有在您访问它们时才会加载标记为lazy="true"
的所有属性。请注意,只要您访问其中一个,就会加载所有带lazy="true"
的属性
根据SO的回答,非强制性一对一关系不支持Lazy-Loading。
那么,为了解决这个问题,为什么不摆脱这种一对一的关系呢?如果您在90%的时间内不需要详细信息,我会考虑删除关系并使用单独的存储库方法,只允许您检索指定PhoneDetails
的Phone
。
继续你的例子,我最终得到这个:
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 ){}
}
以上是关于NHibernate有一个懒惰的负载的主要内容,如果未能解决你的问题,请参考以下文章