Common Mistakes When Using OR/M

David Hayden has posted about the Active Record pattern, and in particular, about using Castle.ActiveRecord. In the examples, he has a class with this structure:

public class Post
{
  public int PostId;
  public int BlogId;
  public int CategoryId;
}

I think that he did it so he would have an easy time explaining it, but I feel compelled to respond to this, because this is an anti pattern that I see a lot of OR/M new comers do. You shouldn'y work with explicit Ids when you are using you objects. A Post object shouldn't know what to do with an integer called BlogId. That is the responsability of the OR/M implementation. You shouldn't bring the database structure into your domain model.

Here is how the class should look like:

public class Post
{
  public int PostId;
  public Blog Blog;
  public Category Category;
}

Working with explicit Ids means that the OR/M can do a lot less for you, since it doesn't have enough information. For instance, it cannot eagerly load the Blog object, since it doesn't know about it. All it know is that you wanted to load an integer, and that is all.

Print | posted on Tuesday, June 13, 2006 11:12 PM

Feedback


Gravatar

  6/14/2006 12:03 AM Murat

I definately aggree with the practice you are following here. I think in cases where you do not need the ID information you can make it private. Of course it also depends on the OR/M you are using and the reflection it uses. But if you are into DDD apart from the "aggregates" I think "entity" object does not need to expose their ID information to the outside world.


  6/14/2006 2:06 AM Sachin Rao

Would you do that with lookup tables as well, especially when you are displaying it in a composite control? I'd rather map it to an enum and convert the value into a displayable val rather than have to fetch a description of that lookup type from the db.


  6/14/2006 2:09 AM Sachin Rao

I just think that sometimes the Id becomes intrinsic to your domain logic, which would perhaps be the only case which would warrant having it in the class.

Otherwise, I'd agree the business model does not need to know how it is persisted in the db.


Gravatar

#  6/14/2006 4:27 AM Ayende Rahien

@Murat,
Yes, the only Id should be the entity PK.

@Sachin,
I fully agree about lookup tables, I turn them into enums and forget about thmem. I view them as completely a toll that is supposed to:
- Catch me by FK violation if I add the wrong value
- Allow me to join against it when I need to check the data.


Gravatar

#  6/14/2006 4:29 AM Ayende Rahien

@Sachin,
Can you explaing what you mean by the Id being intrinsic to your domain logic? Do you mean a Pk with a business value.


  6/14/2006 4:44 AM Sachin Rao

Like when you have to create a list of items to be batch-processed at a later stage, for example.


  6/14/2006 4:49 AM Sachin Rao

For example creating a list of Dispatches for Items in Orders that have been paid for by Customers.

This entails creating a list of Items that need to be sent out today.

It does seem having a list of ItemId's would be really handy.


  6/14/2006 5:02 AM Sachin Rao

Just to elucidate that example,
ItemId is a primary key referenced by Orders and Dispatches.

When Order.Paid=true
Add order.ItemId, Order.CustomerID to a list to be processed tonight.


Gravatar

#  6/14/2006 5:13 AM Ayende Rahien

@Sachin,
Depending on where you are doing this adding.
In this case, a DB Trigger may be appropriate, and then of course I would deal with the Ids.
If I was doing it on the application, I wouldn't do it this way, but simply add it to the list of items of items to process and save it, letting the OR/M handle it.


Gravatar

  6/14/2006 7:17 AM Sachin Rao

Hmm... bad example. I suppose you don't have to fetch each Item in the list. You could probably just create empty Item objects with the primary key set and then assign it to the list of items.

Your OR/M should be able to handle that. Duh!

Sachin


#  6/14/2006 5:15 PM David hayden

hehe...

Yes, I only did it that way to demonstrate Castle Project's ActiveRecord. For the example, I didn't create Blog or Category Domain Objects yet because I wasn't ready to talk about relationships yet. You make a good point, however.

Dave

Comments have been closed on this topic.