NHibernate 通过 session.Load() 创建代理,而不是通过 Linq 或 Criteria API [英] NHibernate creates proxy via session.Load(), but not via Linq or Criteria API

查看:19
本文介绍了NHibernate 通过 session.Load() 创建代理,而不是通过 Linq 或 Criteria API的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have an odd problem in my current project. Lazy loading for queries does not work. When I query a list, nhibernate fetches all associations separately.

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

I extracted small parts of it and put it into a separate solution. Basically what I've got now, is a Account-Table and a AccountSync-Table. Both have an ID and a URL, while the ID is just a 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 加载一个对象时:

When I now load a object via it's guid:

var account = session.Load<HippoAccount>(accountId);
Console.WriteLine(NHibernateUtil.IsPropertyInitialized(account, "Sync"))

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

... it returns false and account itself is a proxy.

但是当通过标准 API 加载列表时:

But when loading a list via the criteria API:

var account = (HippoAccount)session
    .CreateCriteria(typeof (HippoAccount))
    .Add(Restrictions.Eq("Id", accountId))
    .List()[0];

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

... the property Sync gets initialized (firing a second select query), and the returned object is not a proxy.

这是默认行为吗?我做错了什么?

Is that default behaviour? What am I getting wrong?

映射为:

<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 中有很多东西可以防止延迟加载.

After quite some more research, I found the answers. Answers, because there are many things that can prevent lazy loading in NHibernate.

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

  1. Query vs. session.Load: When fetching an item via session.Load() you get a proxy. But as soon as you access any property, lets say the Url, the object is fetched including all it's associations that doesn't support lazy loading.

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

property-ref: Lazy loading only works over a objects id. When an property-association is resolved via a different column in the target entity, NH fetches it eagerly. Not that this wouldn't be possible, it's just not implemented: Bug

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

not-found="ignore" allows invalid foreign keys, that is, if the referenced entity isn't found NH will init the property with null. NH doesn't intercept the property-access for lazy loading, but instead assignes a object proxy. With not-found="ignore" it can't decide if the property should be set to null or a proxy for the given, possibly invalid, foreign key. This could possibly be solved by intercepting the property access.

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

When disabling not-found="ignore" and property-ref the schema export would generate constraints that enforce a circular reference. Not good! The correct mapping would then be a constrained one-to-one relationship, where the key for HippoAccountSync must have a generator foreign.

资源

这篇关于NHibernate 通过 session.Load() 创建代理,而不是通过 Linq 或 Criteria API的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆