NHibernate-在不延迟加载整个对象的情况下访问关联对象的ID

NHibernate-在不延迟加载整个对象的情况下访问关联对象的ID,nhibernate,associations,lazy-loading,Nhibernate,Associations,Lazy Loading,我有两个关联的业务对象-A和B。 关联是(A->B)多对一的,B.Id是A中的外键(因此A在DB中有A.B_Id) 我用lazy=true解决了我的大部分问题, 然而,在A的ToString中,我还想打印A.B.Id,我不需要进一步访问DB就可以打印A.B.Id。但是访问A.B会激活代理,因为这不在开放会话的上下文中,所以会引发异常 一个简单但丑陋的解决方案是拥有A.B_id属性。但这是我们一开始试图避免的一部分。 有什么“有机”的方法可以做到这一点吗?:) 谢谢 更新:只需阅读缓存和Sess

我有两个关联的业务对象-A和B。 关联是(A->B)多对一的,B.Id是A中的外键(因此A在DB中有A.B_Id)

我用lazy=true解决了我的大部分问题, 然而,在A的ToString中,我还想打印A.B.Id,我不需要进一步访问DB就可以打印A.B.Id。但是访问A.B会激活代理,因为这不在开放会话的上下文中,所以会引发异常

一个简单但丑陋的解决方案是拥有A.B_id属性。但这是我们一开始试图避免的一部分。 有什么“有机”的方法可以做到这一点吗?:) 谢谢


更新:只需阅读缓存和Session.Get vs.Session.Load。在此之前,我只知道,如果对象不存在,一个抛出异常(Session.Load),另一个返回空对象(Session.Get)。在阅读了有关缓存的内容后,很明显Session.Load会将代理返回给对象,并且只有在访问ID以外的属性时才会延迟获取代理,这与我从关联中需要的非常相似!
现在,我添加了单独的对象Id(将B_Id添加到A,这样我就可以作为A.B_Id而不是使用A.B.Id来访问它)

原因与我为所有多对一关系使用显式A.B-Id属性完全相同。我不认为这是一个快速而肮脏的解决方案,因为它为这个问题提供了一个解决方案,而且很大的灵活性是保存更新区域,即我不需要从数据库中获取B对象,只是为了将其分配给a,以便在查询字符串或其他地方有B_ID时创建关联

我的映射文件通常如下所示:

<property name="CreatorID" column="CreatorID" type="Int32" not-null="true" />
<many-to-one name="Creator" column="CreatorID" class="SystemUser" insert="false" update="false" cascade="none" />

正如您所见,这两个属性中的一个必须是只读的,以避免在发生插入或更新时NHibernate将此列发送到数据库2次。上面使用insert=“false”update=“false”属性将多对一属性设置为只读,但如果愿意,可以改为使用CreatorID属性为只读

只有多对一,您的实体类a中没有一个属性来保存B.ID值。获取它的唯一方法是访问B对象,它将触发代理,并向数据库发出查询(如果尚未在会话中加载)


我很高兴听到任何其他提供解决方案并提供同样灵活性的选项

如果您使用的是NHibernate 3.2或更高版本,则可以使用以下代码获取关联对象的id,而无需再次往返数据库以加载整个对象:

using NHibernate.Proxy;
...
object id = null;
if (obj.IsProxy()) // obj is the object you want to get its identifier.
{
    var proxy = obj as INHibernateProxy;
    if (proxy != null)
    {
        var li = proxy.HibernateLazyInitializer;
        if (li != null) 
            id = li.Identifier;
    }
}

您可以使用Nhibernate会话的GetIdentifier方法:

session.GetIdentifier(obj);

正如我所说,只是为了日志打印等,在A的ToString()中。我不需要B中的其他字段。只需要ID。我仍然希望这可以只用A.B.ID完成-我不喜欢重复的数据-我有这些属性并删除了它们。。。我将进一步调查此事,但目前我将这样做。谢谢@尤纳坦卡尼完全同意。这也有一个主要的性能问题。将大量n个“代理”实体添加到一个实体集合(具有一个集合支持类型),它会降低性能,因为n个选择(每个代理一个)会按顺序执行,就像
集合一样。Add
会完成它的任务。