Search code examples
c#.netfluent-nhibernaterepositoryobject-graph

FluentNhibernate, retrieve partial Object Graph


So I will call a repository to retrieve the root object of a complex object graph, using FluentNHibernate. But for some sub-level objects I don't want to retrieve all elements, but only those where a date parameter equals certain condition. In below code, I want the lower level Order object to be filtered in this way by the OrderTime field.

Meaning I want to retrieve all UserGroups, with all Users, but the Orders object of each User shall only contain orders from a specific date or date range.

So what are my options on how to retrieve this object graph? I don't want lazy loading, I just want to specify a handful of different retrieval conditions, which will never change. So they can be separate functions of the repository, like suggested at the end. But how would I go about coding those methods, how to specify these conditions?

Objects:

public class UserGroup
{
    public int Id;
    public IList<User> Users;
}

public class User
{
    public int Id;
    public string Name;
    public IList<Order> Orders;
}

public class Order
{
    public int Id;
    public decimal Price;
    public System.DateTime OrderTime;
}

Repository:

public class UserGroupRepository
{    
    public List<UserGroup> GetAll()
    {
        using (ISession session = FNH_Manager.OpenSession()) {
            dynamic obj = session.CreateCriteria(typeof(UserGroup)).List<UserGroup>();
            return obj;
        }
    }
}

Potential new Repository methods: ?

public List<UserGroup> GetAll_FilterOrderDate(System.DateTime _date)
{
}

public List<UserGroup> GetAll_FilterOrderDate(List<System.DateTime> _dates)
{
}

Solution

  • It really depends on what you want to do with the orders.

    Is there a reason you need to query on the aggregate root? Would it make sense to query over the actual orders by date instead? So you'd end up with:

    session.QueryOver<Order>().Where(t => t.OrderDate > ...);
    

    If your associations are set up correctly you'll still be able to navigate to the user.

    Personally I find the repository pattern to be a bit restrictive and would rather use query objects, so you'd end up with something like:

    queryService.FindAll<UserGroup>(new GetAllByFilterOrderDate(DateTime.Now));
    

    However if the concept of a repository works for you then by all means stick to it, but it means you'll try to force your object model into this 'UserGroup' centric view.