我有这个 NHibernate 模型:
public class RootTable
{
public virtual string Name { get; set; }
public virtual string Description { get; set; }
public virtual DateTime? Start { get; set; }
public virtual DateTime? Finish { get; set; }
public virtual IList<Leaf1> ChildCollection1 { get; set; }
}
public class Leaf1
{
public virtual int ID { get; set; }
public virtual string Info1 { get; set; }
public virtual string Info2 { get; set; }
public virtual RootTable Parent { get; set; }
}
public class RootMapping : ClassMap<RootTable>
{
public RootMapping()
{
Table("RootTable");
Id(c => c.Name);
Map(c => c.Description, "Desc").Length(20);
Map(c => c.Start).Length(20);
Map(c => c.Finish).Length(20);
HasMany(c => c.ChildCollection1)
.Cascade.All()
.LazyLoad()
.Inverse();
}
}
public class Leaf1Mapping : ClassMap<Leaf1>
{
public Leaf1Mapping()
{
Table("LeafTable1");
Id(c => c.ID, "RowID").GeneratedBy.Identity();
Map(c => c.Info1).Length(20);
Map(c => c.Info2).Length(20);
References(c => c.Parent).Column("Parent").LazyLoad();
}
}
我想要做的是访问Leaf1 中引用列的值而不延迟加载 RootTable。
换句话说,我有这个:
this.LogMessage("Loading leaves...");
var allleafs = session.CreateCriteria(typeof(Leaf1)).List<Leaf1>();
this.LogMessage("Loaded leaves...");
var leaf = allleafs[0];
this.LogMessage("Leaf metadata:");
// This causes a lazy-load of the RootTable object.
this.LogMessage("Leaf parent is " + leaf.Parent);
现在我真正想要的是“父”的值,因为它存储在底层数据库中——我不关心父对象,我不想加载它,我想做的就是获取原始值。我无法访问包含值(即leaf.Parent.Name
)的字段,因为我希望它以通用方式工作......
[背景]
最终,这是插入到使用 NHibernate 拦截器的审计框架中,因此这需要以通用方式工作,以便对于传入的任何对象,我都可以报告更改的值。子节点完全有可能在根节点没有变化的情况下发生了变化,所以当拦截器OnFlushDirty()
被调用时,我不希望拦截器导致其他对象的延迟加载。
我知道我可以直接引用父属性(例如,我可以说“leaf.Parent.Name”),这将使我得到没有延迟加载的值,但似乎没有一种快速的方法来确定“名称”是我要返回的关键属性。
[编辑添加...]
因为我得到一个空引用异常,所以走树似乎不起作用:
var theType = leaf.Parent.GetType();
// This line returns a NULL due to the proxy class.
var metadata = factory.GetClassMetadata(theType);
var idProp = metadata.IdentifierPropertyName;
var prop = theType.GetProperty(idProp);
var val = prop.GetValue(leaf.Parent, null);
this.LogMessage("Leaf parent is " + val);
现在, theType 返回为RootTableProxy
,因此只是一个占位符,因为未加载主类。这意味着metadata
为空,因为没有类元数据,因此idProp
因空引用异常而失败。
所以我实际上看不到如何在没有延迟加载的情况下获取引用的列值:这肯定不对吗?
编辑添加(更多!)
我认为使用 session.GetIdentifier() 找到了一个简单的解决方案。然而,这似乎并不适用于所有情况:在调用session.GetIdentifier(state[i])
某些对象的拦截器中导致异常指出该对象不是当前会话的一部分,因此仍在寻找不诉诸反射的更可靠的解决方案. 欢迎任何想法...