使用nHibernate的ISession和Eager Loading来分担关注点

时间:2011-03-10 21:41:33

标签: nhibernate fluent-nhibernate asp.net-mvc-3

我有一个使用Fluent NHibernate和ASP.NET MVC构建的应用程序。目前它分为5个项目。

WEB

ASP.NET MVC项目仅包含HTML,CSS,控制器和非常项目特定的验证器和模型绑定器,以及IoC容器Ninject

模型

Models项目包含域对象IRepository<T>,使用存储库的服务以及与数据库操作无关的辅助代码。

PERSISTENCE

Persistence项目包含Fluent nHibernate Mapping,ISessionFactory映射,Repository<T> : IRepository<T>实现等。

PERSISTENCE.UTILITIES

这是一个辅助项目,与我的实际最终产品几乎没有关系。这就是我要测试数据库播种,快速设置的默认集​​合等等。

TEST

单元测试项目


我遇到的问题是在ModelsPersistence之间。当我需要使用预先加载时,有某些次。在nHibernate中,我会使用Query<T>().Fetch(...)来执行此操作。这样可以正常工作,除了Models.dll没有nHibernate的概念。除了System.dll之外,它没有任何库的概念,并且完全是独立的。

我是否有一种特定的方法可以在不知道IRepository的情况下添加将Eager加载到我的NHibernate.Linq的功能?我无法添加一个采用任何类型的lambda表达式的方法,其中包含Fetch因为我的持久层在Model层中不存在。但IRepository<T>存在于模型层中,因为它在Service对象中使用,而Service对象也没有数据库的概念。他们只需访问适当的存储库。存储库不会公开Web层,只会显示相应的服务。

有什么想法吗?

3 个答案:

答案 0 :(得分:2)

我想我理解你......所以它基本上归结为你如何实现存储库模式。您可以在流畅的映射中设置急切的加载,但不管如此,听起来您只想在少数情况下进行急切加载,因此NHibernate的东西仍然需要使用当前设置泄漏到您的Model项目中。

回到整个存储库模式的事情,我能想到的一个选择是让你的存储库稍微聪明一些。

E.g。在您的Models项目中:

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

然后在您的Persistence项目中:

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 :(得分:1)

如果您将IRepository定义为IQueryable,则可以在存储库本身上使用LINQ。例如:

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;
}

然后你可以使用(一旦引用System.Linq):

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

答案 2 :(得分:0)

  

我遇到的问题是在模型和持久性之间。那里   在某些时候我需要使用预先加载。在nHibernate中,我   会使用Query()。Fetch(...)来做到这一点。这样可以正常工作,   除了Models.dll没有nHibernate的概念。它没有概念   除System.dll之外的任何库都是完全独立的。

在我看来,可以从NH中获益最多的一个图书馆没有使用它。只有Web和Persistence正在使用NH,但它是使用隐藏在低功能IRepository后面的NH的抽象版本的模型。我建议你允许NH进入模型并使用ISession,它实际上是一个加强的功能库。