views:

189

answers:

1

Hi,

From the text "The Repository" pattern is a Mediator between the Domain and Data Mapper layers. Cool. So for example, maybe there is a Repository interface and Base Domain Object like so

public interface Repository<DomainT> where DomainT : DomainObject{
    DomainT Get(Object id);
}

Then a concrete implementation would be

public class ThreadRepository : Repository<Thread>{
    public Order Get(Object id){
         return _session.Find(typeof(Thread),id);
    }
}

Now my question is this, A Thread can have many posts, like StackOverflow, lets say this Thread has 300 posts. Using the above statement, I will get the Thread Object, and I only want to display lists of 20 items, so I will access the Post Collection property of the Thread object which, due to LazyLoading will fetch all 300, ready for me to handle how I please.

Would it be more efficient to have a method on the Repository called

GetThreadPosts(object threadID, int pageSize, int index);
GetThreadPostCount(object threadID);

Or would the second level cache make this call relatively cheap, as in getting back the 300 posts, preserves my Domain Model.

  • What if there were 3000 or 30,000 Posts, is the Post Collection property on the Thread Domain Model still valid?

  • If it is better to have the GetThreadPosts & GetThreadPostCount, does this mean that a property on the Thread object of List is redundant?

  • Should it be the case that I should have a limit in mind for when a List property on an object is only viable if say the number of items it is likely to have will not exceed a certain number?

Thanks for your time,

Andrew

+2  A: 

The way lazy loading works is that it will defer the execution of the database join query until you access the Posts collection. Now if you are going to show only 30 posts on the page while there are 30000 posts in the database that satisfy your criteria loading all the collection would be a waste.

In my opinion paging should be done at the database level. In this case I would remove the Posts collection from the Thread class and Post should belong to a Thread which will allow you to construct your query. Also a single method would be enough to get the paged Posts collection and the total number of posts:

public IEnumerable<Post> GetPosts(object threadID, int pageSize, int index, out totalPosts) 
{
    var results = session
        .CreateMultiCriteria()
        .Add(GetCriteria(threadID)
             .SetFirstResult((index - 1) * pageSize)
             .SetMaxResults(pageSize)
        )
        .Add(GetCriteria(threadID)
             .SetProjection(Projections.RowCount())
        )
        .List();

    var counts = (IList)results[1];
    totalPosts = (int)counts[0];
    return ((IList)results[0]).Cast<Post>();
}

private DetachedCriteria GetCriteria(object threadID)
{
    return DetachedCriteria
        .For<Post>()
        .Add(Expression.Eq("Thread.Id", threadID));
}
Darin Dimitrov
Thank for the explanation. That sounds extremely logical!! :-)
REA_ANDREW