nHibernate 需要延迟加载吗?
Posted
技术标签:
【中文标题】nHibernate 需要延迟加载吗?【英文标题】:Is Lazy Loading required for nHibernate? 【发布时间】:2010-10-20 15:11:06 【问题描述】:我花了很长时间,但我终于让 nHibernate 的 Hello World 工作了。在我进行“延迟加载”之后它起作用了。老实说,我无法告诉你为什么这一切都有效,但它确实有效,现在我正在阅读你不需要延迟加载。有没有人拥有一个让 nHibernate 正常工作的你好世界?你必须有延迟加载吗?我问是因为我想使用 nHibernate,但我需要了解它是如何工作的。
谢谢。
你知道没有这么多开销的 hello world 吗?
使用延迟加载会更好吗?
编辑:我使用的是 asp.net 3.5。 Web 应用程序项目。
【问题讨论】:
A 在我的回答中添加了另一个部分。 [***.com/questions/31366236/… 【参考方案1】:我不明白您所说的“我做了延迟加载”是什么意思。延迟加载是一个功能,默认开启,不喜欢可以关闭。
有两种延迟加载:用于引用其他实体和用于列表。
给定这个实体:
class Entity
// pk
int id get; private set;
// reference to another entity
User MyUser get; set;
// list to other entities
IList<Comments> MyComments get; set;
延迟加载对 User 的引用
如果您对 User 进行延迟加载,则需要定义 User 类的所有成员 virtual。 NHibernate 将创建一个所谓的代理。代理是在运行时定义的一个类,它派生自 User。您的代码以用户身份访问它,并且不知道它是一个子类。但是,当您第一次访问其中一个成员时,会从数据库中加载属性。
如果你想关闭 User 类的延迟加载,你需要在它的映射中这样做:
<class name="User" lazy="false"> ...
然后 NHibernate 总是创建用户类型的实例,没有代理。你不需要任何虚拟的东西。
cmets列表的延迟加载
如果您在 cmets 列表上使用延迟加载,则执行延迟加载的是列表本身。如果您第一次访问该列表,它会从数据库中加载。 NHibernate 使用实现 IList 的列表,但不是 List。
如果要关闭列表中的延迟加载,在Entity的映射中这样做:
<class name="Entity">
<bag name="MyComments" lazy="false" >
...
通常,延迟加载是一件好事,您的应用程序不必太在意它。但也存在一些风险。例如,如果您序列化一个实例,并且它是一个代理,您将得到一个未初始化的代理,而不是任何有用的东西。延迟加载仅在会话打开时才有效。使用延迟加载并不总是更快。如果您无论如何都需要加载所有数据,则将其加载到一块会更快。
所以配置需要谨慎。
编辑:
回答您最初的问题:NHibernate 需要延迟加载吗?不可以。但是:我的应用程序需要延迟加载吗?很可能是的。
我认为,只有小型且相当琐碎的应用程序才不需要延迟加载。如果您的系统包含许多持久类,则需要延迟加载。
【讨论】:
NH 参考文档与"Since lazy initialization can lead to bugs [...], non-laziness is the default."
和 "NHibernate uses lazy select fetching for collections and lazy proxy fetching for single-valued associations.
完全自相矛盾 - 用于收藏
@Chris:第一句话很旧。懒惰是自版本以来的默认设置(我不知道)。第二个陈述是我实际上试图解释的。【参考方案2】:
如果您使用 hbm.xml 文件进行映射,只需将 lazy="false"
添加到 <class>
元素即可让您对所有简单属性进行非延迟加载。默认情况下,外部实体仍然是惰性的。为了让他们渴望将lazy="false"
添加到映射元素。预加载的一个好处是您将不再需要实体类上的虚拟属性。
编辑: 如果您真的想了解幕后发生的事情,NHibernate 使用 log4net 记录所有内容。添加
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
<!-- Rest of config sections here -->
</configSections>
<log4net>
<appender name="SQLFileAppender" type="log4net.Appender.RollingFileAppender, log4net">
<param name="File" value="C:\Logs\SQL.log" />
<param name="AppendToFile" value="true" />
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%date [%thread] %-5level %logger - %message%newline" />
</layout>
</appender>
<logger name="NHibernate.SQL" additivity="false">
<level value="DEBUG" />
<appender-ref ref="SQLFileAppender" />
</logger>
</log4net>
在你的web.config里面<configuration>
里面会吐出所有SQL NHibernate生成的文件c:\logs\sql.log
【讨论】:
以上是关于nHibernate 需要延迟加载吗?的主要内容,如果未能解决你的问题,请参考以下文章