代码之家  ›  专栏  ›  技术社区  ›  Lars Corneliussen

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

  •  9
  • Lars Corneliussen  · 技术社区  · 15 年前

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

    我提取了它的一小部分,并将其放入一个单独的解决方案中。基本上我现在得到的是一个Account表和一个AccountSync表。两者都有一个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

    但通过criteria API加载列表时:

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

    ... 财产 Sync 初始化(触发第二个select查询),返回的对象不是代理。

    映射为:

    <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>
    
    1 回复  |  直到 15 年前
        1
  •  13
  •   Lars Corneliussen    15 年前

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

    1. 查询与会话加载: session.Load() 你有一个代理。但一旦你进入 财产,比方说 Url

    2. 属性参考: 延迟加载只能在对象id上工作。当通过目标实体中的不同列解析属性关联时,NH会急切地获取它。 Bug

    3. 未找到=“忽略” 外键,也就是说,如果找不到引用的实体,NH将使用null初始化属性。NH不会拦截延迟加载的属性访问,而是分配一个对象代理。具有 not-found="ignore" 它无法决定是将属性设置为null还是为给定的可能无效的外键设置代理。 这可能通过拦截属性访问来解决。

    4. 禁用时 未找到=“忽略” property-ref 模式导出将生成强制循环引用的约束。不好的!正确的映射将是一个受约束的一对一关系,其中 HippoAccountSync 必须有发电机 foreign .