views:

725

answers:

4

Let's say I've got the following ActiveRecord class:

[ActiveRecord]
public class Account
{
    ...

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

Currently, to set the value of the CustomerId field I have to get the entire Customer object from the database and assign it to the Account:

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

This isn't very efficient. I'd rather set the value of CustomerId field directly without round-tripping the database, e.g.

account.CustomerId = 1;

What's the correct way to do this?

+1  A: 

It depends, really. You can implement caching to lessen the burden of obtaining data that might not change too often like customers. Beware this might be premature optimisation though.

Neil Barnwell
+1  A: 

I agree with Neil, but if you really want this, you can do it with IQuery.ExecuteUpdate()

Mauricio Scheffer
+1  A: 

I don't know how Castle ActiveRecord uses NHibernate to load objects from the database (using ISession.Get or ISession.Load?), but I know that the following can be done with NHibernate:

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

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

Here, ghostCustomer will be an unitialized proxy object, whose fields will be lazy loaded the first time they are accessed. But since we only use it to assign the customer relation on the account, it will never actually be loaded.

Thus, the only database access in this example will happen when loading the account and afterwards when the session is flushed and the account must be updated.

mookid8000
A: 

You can implement MK8k's solution in ActiveRecord. It would look like this:

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

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

Two important points:

The Customer.Find must be in a SessionScope. The Find method checks and will fully load your object if a SessionScope is not defined.

The Customer class must be defined as lazy. NHibernate will not use a proxy for a non-lazy class.

oillio