Where to put NHibernate query logic?

I am trying to configure the correct domain architecture using Fluent NHibernate and Linq for NHibernate. I have my controllers calling Repository classes that make NHibernate under the hood and pass ICollections of data. This seems to work well, as it abstracts out data access and preserves NHibernate 's small print functionality.

However, now I find situations where my controllers must use the same data calls in a different context. For example, my repo returns a list of users. This is great when I want to display a list of users, but when I want to start using child classes to display roles, etc., I run SELECT N + 1 problems. I know how to change this in NHibernate, so it uses joins instead. but my specific question is: WHERE did I put this logic? I do not want every call to GetAllUsers () to return roles either, but I need some of them.

So, here are my three options that I see:

  • Change the setting in my mapping so that the roles are attached to my request.
  • Create two repository calls - GetAllUsers () and GetUsersAndRoles ().
  • Return the IQueryable from the repository to the controller and use the NHibernate Expand method.

Sorry if I didn’t explain it very well. I just jump into DDD and many of this terminology is still new to me. Thanks!

+4
source share
4 answers

As lomaxx points out, you need a request. Expand

So that your repository does not obscure all sorts of methods for any possible situation, you could create query objects that configure queries.

I posted some examples using the ICriteria API on my blog . The ICriteria API has FetchMode instead of Expand , but the idea is the same.

+2
source

I am trying to save all the query logic in my repositories and will only try to drop the ICollection from them.

In your situation, I would pass some parameters to determine whether you want to load roles or not, and build IQueryable this way. For instance:

 GetAllUsers(bool loadRoles) { var query = session.Linq<Users>(); if(loadRoles) query.Expand("Roles"); return query.ToList(); } 
+1
source

I would choose 2 by creating two repositories. And maybe I would think about creating another repository call for GetRoleByUser (User User). This way, you can access the user role when changing the user selection in a separate thread, if necessary, so that it will increase your productivity and will not load all user roles for each of your users, which will require most resources.

0
source

It looks like you are asking if it is possible that GetAllUsers() return only user objects and sometimes return users and roles.

I would either make a separate repository method called GetRolesForUser(User user) , use lazy loading for GetAllUsers(bool loadRoles) , or use GetAllUsers(bool loadRoles) mentioned in lomaxx answer.

I would lean towards lazy downloads or a separate method in your repository.

0
source

Source: https://habr.com/ru/post/1309424/


All Articles