我正在使用Castle ActiveRecord,但这个问题也适用于NHibernate,因为适用于NHibernate的解决方案适用于ActiveRecord。无论如何,我所拥有的是这样的基础表结构:
表A -hasMany->表B
我有相应的对象EntityA和EntityB。 EntityA具有IList的EntityB对象。这部分工作正常。现在,我希望EntityB能够对EntityA进行某种引用。我知道我可以使用EntityB上的BelongsTo属性给它一个实际的引用回到完整的EntityA类型,如:
[BelongsTo("tableAid")]
public EntityA Parent { get; set; }
但我真正想做的是:
[BelongsTo("tableAid")]
public int ParentId { get; set; }
因此,EntityB只会存储父对象的ID,而不是对实际对象的引用。这是一个微不足道的例子,但我有充分的理由想要采用这种方法。在我正在处理的应用程序中,我们有显示特定EntityB类对象的页面,我们希望这些页面包含指向相应父页面的链接(如在超链接中)。我们可以通过使用上面的第一种方法来做到这一点,但这需要在我真正需要的只是ID时加载整个EntityA对象。这不是什么大不了的事,但它似乎很浪费。我知道我可以使用延迟加载,但同样,这似乎更像是对我的黑客...
我尝试使用[Property]属性标记外键,如下所示:
[Property]
public int ParentId { get; set; }
此方法的问题是,当您在新对象树上执行EntityA.SaveAndFlush()时,EntityB.ParentId保持为null。正确的值正在写入数据库,我可以通过执行EntityA.Refresh()强制将值重新导入EntityB.ParentId,但同样,这似乎有点像黑客。
答案 0 :(得分:2)
延迟加载正是你想要的 - 而且它也不是黑客,它是NHIbernate的一部分经过充分测试和烘焙,是性能调优任何实质性NHibernate应用程序的重要工具。
如果您要将“父”EntityA标记为延迟加载,请参阅EntityB.Parent.Id根本不会加载EntityA(因为幕后NHIbernate在加载EntityB时已经加载了EntityA的id) - 从而让您进行设置您的链接不会导致性能下降。
答案 1 :(得分:0)
就是这样:
[Property] public int ParentId { get; set; }
...假设ParentId
是实际的列名。
其他一些评论。
首先,您应该考虑延迟加载多对一属性。如果你急切地加载它们,你必须意识到可能的级联的急切负载,这可能会严重影响性能。为此,您必须将延迟加载的类的所有公共成员标记为虚拟。
其次,请注意,每当您与子级回到父级之间没有对应关系的一对多关联时,您必须使FK在数据库中可为空。那是因为当NH创建新的子项时,它将插入父ID为null,然后在第二步中更新它。