对 nHibernate 的 ISession 和预加载的关注点分离感到困惑

发布于 2024-10-21 07:48:40 字数 1076 浏览 2 评论 0原文

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

WEB

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

模型

模型项目包含域对象,IRepository,使用Repository的服务,以及与数据库操作无关的辅助代码。

PERSISTENCE

Persistence 项目包含 Fluent nHibernate 映射、ISessionFactory 映射、Repository等。 :IRepository 实现等。

PERSISTENCE.UTILITIES

这是一个辅助项目,与我的实际最终产品关系不大。这是我放置测试数据库种子、快速设置的默认集​​合等内容的地方。

TEST

单元测试项目


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

有没有一种特定的方法可以在不了解 NHibernate.Linq 的情况下将预加载功能添加到我的 IRepository 中?我无法添加采用任何类型的 lambda 表达式(其中包含 Fetch)的方法,因为模型层中不存在我的持久层。但是IRepository存在于模型层,因为它用在Service对象中,而Service对象也没有数据库的概念。他们只需访问适当的存储库即可。存储库不暴露给Web层,只暴露给适当的服务。

有什么想法吗?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

逆流 2024-10-28 07:48:40

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

回到整个存储库模式,我能想到的一个选择是让您的存储库稍微智能一些。

例如,在您的 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
    }
}

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
    }
}
烟─花易冷 2024-10-28 07:48:40

如果将 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");

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");
提赋 2024-10-28 07:48:40

我遇到的问题是模型和持久性之间的问题。那里
在某些时候我需要使用预加载。在 nHibernate 中,我
将使用 Query().Fetch(...) 来执行此操作。这会工作得很好,
除了 Models.dll 没有 nHibernate 的概念。它没有这个概念
除 System.dll 之外的任何库,并且完全独立。

在我看来,最能从 NH 中受益的图书馆并没有使用它。只有 Web 和持久性使用 NH,但模型使用隐藏在低功能 IRepository 后面的 NH 抽象版本。我建议您允许 NH 进入模型并使用 ISession,它实际上是一个增强的完整功能存储库。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文