2
votes

I have an application built using Fluent NHibernate and ASP.NET MVC. It is divided into 5 projects, at the moment.

WEB

The ASP.NET MVC project contains only the HTML, CSS, Controllers, and very project specific Validators and Model Binders, as well as the IoC container Ninject

MODELS

The Models project contains the domain objects, IRepository<T>, Services that use the Repository, and ancillary code not related to database operations.

PERSISTENCE

The Persistence project contains Fluent nHibernate Mapping, ISessionFactory mapping, Repository<T> : IRepository<T> implementation, etc.

PERSISTENCE.UTILITIES

This is an ancillary project that has little to do with my actual final product. This is where I am putting things like test database seeding, default collections for quick-setup, etc.

TEST

Unit Testing Project


The problem I am running into is between Models an Persistence. There are certain times when I need to use eager loading. In nHibernate, I would use Query<T>().Fetch(...) to do this. This would work fine, except Models.dll has no concept of nHibernate. It has no concept of any library except System.dll and is completely standalone.

Is there a specific way I can add the ability to do Eager loading into my IRepository without knowledge of NHibernate.Linq? I cannot add a method that takes any kind of lambda expression that would include Fetch in it because my persistence layer doesn't exist in the Model layer. But the IRepository<T> exists in the model layer, because it is used in the Service objects, which also have no concept of the database. They simply access the appropriate repositories. The Repositories are not exposed to the Web Layer, just the appropriate Services.

Any ideas?

3
I don't see why you can't just keep the knowledge of eager loading in your Persistence project... Why does you Models project need to know about it?Charlino
I'm asking how to keep it in persistence project. I can't pass a query that has knowledge of the NHibernate Fetch method through my IRepository - but the IRepository has to be in the Models project.Ciel

3 Answers

2
votes

I think I understand you... so it basically boils down to how you're implementing the repository pattern. You could set the eager loading in the fluent mappings BUT regardless of that, it sounds like you only want to do eager loading in a few cases, so therefore NHibernate stuff will still need to leak into your Model project with the current setup.

Going back to the whole repository pattern thing, one option I can think of would be to make your repositories slightly smarter.

E.g. In your Models project have:

public interface IFooRepository : IRepository<Foo>
{
    IQueryable<Foo> GetAllFoosWithBars();
}

Then in your Persistence project have:

public class FooRepository : Repository<Foo>, IFooRepository
{
    public IQueryable<Foo> GetAllFoosWithBars()
    {
        return this.Session.Query<Foo>().Fetch(c => c.Bars);
        //I don't know the return type for .Fetch() off the top of
        //my head, so you might need a .AsQueryable() in there
    }
}
1
votes

If you defined your IRepository as IQueryable, you could use LINQ on the repository itself. For example:

public interface IRepository<T> : IQueryable<T>
{
}

public class Repository<T> : IRepository<T>
{
    public Repository(ISession session)
    {
        query = session.Query<T>();
    }

    public Type ElementType
    {
        get { return query.ElementType; }
    }
    public Expression Expression
    {
        get { return query.Expression; }
    }
    public IQueryProvider Provider
    {
        get { return query.Provider; }
    }

    IQueryable<T> query;
}

Then you can use (once you reference System.Linq):

IRepository<Foo> repo = new Repository<Foo>();
Foo foo = repo.FirstOrDefault(f => f.Bar == "bar");
0
votes

The problem I am running into is between Models an Persistence. There are certain times when I need to use eager loading. In nHibernate, I would use Query().Fetch(...) to do this. This would work fine, except Models.dll has no concept of nHibernate. It has no concept of any library except System.dll and is completely standalone.

Seems to me the one library that could benefit the most from NH isn't using it. Only the Web and Persistence is using NH, but it's the Model that is using the abstracted version of NH hidden behind a low feature IRepository. I propose you allow NH into Models and utilize the ISession, which in reality is a souped up full feature repository.