NHibernate / ActiveRecord:如何在不获取整个对象的情况下设置外键?

时间:2009-02-18 11:45:36

标签: c# nhibernate activerecord castle-activerecord

假设我有以下ActiveRecord类:

[ActiveRecord]
public class Account
{
    ...

    [BelongsTo("CustomerId")]
    public Customer Customer { get; set; }
}

目前,要设置CustomerId字段的值,我必须从数据库中获取整个Customer对象并将其分配给帐户:

Customer customer = Customer.FindById(1);
account.Customer = customer;

效率不高。我宁愿直接设置CustomerId字段的值,而不是往返数据库,例如

account.CustomerId = 1;

这样做的正确方法是什么?

4 个答案:

答案 0 :(得分:2)

我不知道Castle ActiveRecord如何使用NHibernate从数据库加载对象(使用ISession.GetISession.Load?),但我知道NHibernate可以完成以下任务:

var ghostCustomer = session.Load<Customer>(customerId);

var account = session.Get<Account>(accountId);
account.Customer = ghostCustomer;

这里,ghostCustomer将是一个单元化的代理对象,其字段在第一次访问时将被延迟加载。但由于我们只使用它来为帐户分配客户关系,因此它实际上永远不会被加载。

因此,此示例中的唯一数据库访问将在加载帐户时发生,之后在刷新会话时必须更新帐户。

答案 1 :(得分:1)

这取决于,真的。您可以实施缓存以减轻获取可能不会像客户那样经常更改的数据的负担。请注意,这可能是过早的优化。

答案 2 :(得分:1)

我同意Neil,但如果你真的想要这个,你可以用IQuery.ExecuteUpdate()

来做到这一点。

答案 3 :(得分:0)

您可以在ActiveRecord中实施MK8k的解决方案。它看起来像这样:

using (new SessionScope()) {
    var ghostCustomer = Customer.Find(customerId);

    var account = Account.TryFind(accountId);
    account.Customer = ghostCustomer;
}

两个要点:

Customer.Find必须位于SessionScope中。如果未定义SessionScope,Find方法将检查并完全加载对象。

必须将Customer类定义为惰性。 NHibernate不会将代理用于非惰性类。