NHibernate 通过 session.Load() 创建代理,而不是通过 Linq 或 Criteria API

标签 nhibernate lazy-loading criteria

我当前的项目中有一个奇怪的问题。查询的延迟加载不起作用。当我查询列表时,nhibernate 分别获取所有关联。

我提取了它的一小部分并将其放入单独的解决方案中。基本上我现在得到的是一个 Account-Table 和一个 AccountSync-Table。两者都有一个 ID 和一个 URL,而 ID 只是一个 db-guid。

我的类(class)是:

public class HippoAccount
{
    public virtual Guid Id { get; set; }
    public virtual string Url { get; set; }
    public virtual HippoAccountSync Sync { get; set; }
}

public class HippoAccountSync
{
    public virtual Guid Id { get; set; }

    public virtual string Url { get; set; }
    public virtual HippoAccount Account { get; set; }
}

当我现在通过它的 guid 加载一个对象时:
var account = session.Load<HippoAccount>(accountId);
Console.WriteLine(NHibernateUtil.IsPropertyInitialized(account, "Sync"))

...它返回 false并且帐户本身是一个代理。

但是当通过标准 API 加载列表时:
var account = (HippoAccount)session
    .CreateCriteria(typeof (HippoAccount))
    .Add(Restrictions.Eq("Id", accountId))
    .List()[0];

... 属性(property) Sync被初始化(触发第二个选择查询),并且返回的对象不是代理。

这是默认行为吗?我怎么了?

映射是:
<class name="HippoAccount" table="AllAccounts">
  <id name="Id" type="guid">
    <generator class="guid"/>
  </id>
  <property name="Url" />

  <many-to-one 
           class="HippoAccountSync"
           name="Sync"
           not-found="ignore"
           property-ref="Url">
    <column name="url" />
  </many-to-one>
</class>

<class name="HippoAccountSync"
       mutable="false"
       table="Accounts">

  <id name="Id" type="guid">
    <generator class="guid"/>
  </id>

  <property name="Url">
    <column name="serviceUri" />
  </property>

  <many-to-one class="HippoAccount"
               name="Account"
               property-ref="Url"
               not-found="ignore">

    <column name="serviceUri" />
  </many-to-one>

</class>

最佳答案

经过更多的研究,我找到了答案。答案,因为在 NHibernate 中有很多东西可以防止延迟加载。

  • 查询 vs. session.Load:通过 session.Load() 获取项目时你得到一个代理。但是只要您访问 任何 属性,可以说 Url ,该对象被获取,包括所有不支持延迟加载的关联。
  • 属性引用:延迟加载仅适用于对象 ID。当通过目标实体中的不同列解析属性关联时,NH 会急切地获取它。并不是说这是不可能的,只是没有实现:Bug
  • not-found="忽略"允许 无效 外键,也就是说,如果未找到引用的实体,NH 将使用 null 初始化该属性。 NH 不会拦截延迟加载的属性访问,而是分配一个对象代理。与 not-found="ignore"它无法决定是否应将属性设置为 null 或为给定的可能无效的外键设置代理。这可能可以通过拦截属性访问来解决。
  • 禁用时 not-found="ignore"property-ref模式导出将生成强制循环引用的约束。不好!正确的映射将是受约束的一对一关系,其中 HippoAccountSync 的键是必须有发电机foreign .

  • 资源
  • Select statement issued for each not-found=ignore
  • Lazy-load conflicts with Property-ref in Many-to-One Mapping
  • Google groups discussion
  • 关于NHibernate 通过 session.Load() 创建代理,而不是通过 Linq 或 Criteria API,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1643905/

    相关文章:

    Hibernate Criteria contains-in 与表的关联

    c# - NHibernate 嵌套类映射问题

    nhibernate - Fluent NHibernate - 将多行展平为一个实体

    Angular Lazy 加载模块 - 子路由中的问题

    ios - UICollectionView visibleCells 在滚动前返回 0

    java - 将日期从字符串类型转换为日期数据类型时出现类转换异常

    java - 搜索条件不起作用

    c# - NHibernate 中的鉴别器查询

    c# - 流利的 NHibernate : ManyToMany Self-referencing mapping

    java - 了解如何在 hibernate 中的急切(非惰性)加载中获取对象