【问题标题】:NHibernate creates proxy via session.Load(), but not via Linq or Criteria APINHibernate 通过 session.Load() 创建代理,而不是通过 Linq 或 Criteria API
【发布时间】:2009-10-30 20:31:35
【问题描述】:

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

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

我的课程是:

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];

...属性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 lazy-loading criteria


【解决方案1】:

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

  1. 查询与 session.Load: 当通过 session.Load() 获取项目时,您将获得一个代理。但是,只要您访问 任何 属性,比如Url,就会获取该对象,包括它的所有不支持延迟加载的关联。

  2. property-ref: 延迟加载仅适用于对象 ID。当通过目标实体中的不同列解析属性关联时,NH 会急切地获取它。 并不是说这不可能,只是没有实现:Bug

  3. not-found="ignore" 允许 invalid 外键,也就是说,如果未找到引用的实体,NH 将使用 null 初始化属性. NH 不会拦截延迟加载的属性访问,而是分配一个对象代理。对于not-found="ignore",它无法决定该属性是否应设置为 null 或指定的(可能无效的)外键的代理。 这可以通过拦截属性访问来解决。

  4. 当禁用 not-found="ignore"property-ref 时,架构导出将生成强制循环引用的约束。不好!正确的映射将是一个受约束的一对一关系,其中HippoAccountSync 的键必须有一个生成器foreign

资源

【讨论】:

  • 使用 session.Load(),您当然可以安全地访问代理的 Id 属性而无需访问数据库,因为您给代理提供了开头的 Id。
  • 指向 property-ref 错误的链接不再存在,404 错误。对这个进展有任何想法吗?
猜你喜欢
  • 1970-01-01
  • 2019-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多