NHibernate 查询逻辑放在哪里?
我正在尝试使用 Fluent NHibernate 和 Linq to NHibernate 建立正确的域体系结构。我的控制器调用我的存储库类,这些类在幕后执行 NHibernate 操作并传回数据的 ICollections。这似乎工作得很好,因为它抽象了数据访问并将 NHibernate 功能保留在“细则”中。
但是,现在我发现我的控制器需要在不同的上下文中使用相同的数据调用。例如,我的存储库返回用户列表。当我想要显示用户列表时,这很好,但是当我想要开始利用子类来显示角色等时,我会遇到 SELECT N+1 问题。我知道如何在 NHibernate 中更改它,以便它使用连接,但我的具体问题是我应该把这个逻辑放在哪里?我不希望每个 GetAllUsers() 调用也返回角色,但我确实希望其中一些角色返回。
以下是我看到的三个选项:
- 更改映射中的设置,以便将角色加入到我的查询中。
- 创建两个存储库调用 - GetAllUsers() 和 GetUsersAndRoles()。
- 将我的 IQueryable 对象从存储库返回到控制器并使用 NHibernate Expand 方法。
抱歉,如果我没有很好地解释这一点。我刚刚开始接触 DDD,其中很多术语对我来说仍然是新的。谢谢!
I am trying to set up proper domain architecture using Fluent NHibernate and Linq to NHibernate. I have my controllers calling my Repository classes, which do the NHibernate thang under the hood and pass back ICollections of data. This seems to work well because it abstracts the data access and keeps the NHibernate functionality in the "fine print".
However, now I'm finding situations where my controllers need to use the same data calls in a different context. For example, my repo returns a list of Users. That's great when I want to display a list of users, but when I want to start utilizing the child classes to show roles, etc., I run into SELECT N+1 issues. I know how to change that in NHibernate so it uses joins instead, but my specific question is WHERE do I put this logic? I don't want every GetAllUsers() call to return the roles also, but I do want some of them to.
So here are my three options that I see:
- Change the setting in my mapping so the roles are joined to my query.
- Create two Repository calls - GetAllUsers() and GetUsersAndRoles().
- Return my IQueryable object from the Repository to the Controller and use the NHibernate Expand method.
Sorry if I didn't explain this very well. I'm just jumping into DDD and a lot of this terminology is still new to me. Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
正如 lomaxx 指出的那样,您需要 query.Expand。
为了防止您的存储库因每种可能情况的各种方法而变得模糊,您可以创建进行可配置查询的查询对象。
我在我的博客上发布了一些使用 ICriteria API 的示例。 ICriteria API 有
FetchMode
而不是Expand
,但想法是相同的。As lomaxx points out, you need query.Expand.
To prevent your repository from becoming obscured with all kinds of methods for every possible situation, you could create Query Objects which make configurable queries.
I posted some examples using the ICriteria API on my blog. The ICriteria API has
FetchMode
instead ofExpand
, but the idea is the same.我尝试将所有查询逻辑保留在我的存储库中,并尝试仅从它们传回 ICollection。
在您的情况下,我会传入一些参数来确定您是否想要急切加载角色并以这种方式构造 IQueryable。例如:
I try and keep all the query logic in my repositories and try to only pass back the ICollection from them.
In your situation, I'd pass in some parameters to determine if you want to eager load roles or not and construct the IQueryable that way. For example:
我会选择 2,创建两个存储库。也许我会考虑创建另一个对 GetRoleByUser(User user) 的存储库调用。因此,如果需要,您可以在单独的线程上更改用户选择时访问用户的角色,这样它将提高您的性能,并且不会为每个用户加载每个用户的角色,这将需要大部分资源。
I would choose 2, creating two repositories. And perhaps would I consider creating another repository call to GetRoleByUser(User user). So, you could access a user's role upon user selection change on a seperate thread, if required, so it would increment your performance and won't load every user's roles for each of your users, which would require most resources.
听起来您好像在问是否可以使
GetAllUsers()
有时仅返回用户实体,有时返回用户和角色。我要么创建一个名为
GetRolesForUser(User user)
的单独存储库方法,对角色使用延迟加载,或者使用 lomaxx 的答案中提到的GetAllUsers(bool loadRoles)
。我倾向于延迟加载角色或存储库中的单独方法。
It sounds like you are asking if it is possible to make
GetAllUsers()
sometimes return just the Users entities and sometimes return the Users and the roles.I would either make a separate repository method called
GetRolesForUser(User user)
, use lazy loading for Roles, or use theGetAllUsers(bool loadRoles)
mentioned by lomaxx's answer.I would lean toward lazy loading roles or a separate method in your repository.