NHibernate a rejoint deux collections avec QueryOver et Future

J'ai l'entité de projet et les entités ProjectRole et ProjectUser:

public class Project { ... public virtual IList<ProjectRole> Roles { get; set; } public virtual IList<ProjectUser> ProjectUsers { get; set; } } public class ProjectRole { public int ProjectID { get; set; } public int RoleID { get; set; } } public class ProjectUser { public int ProjectID { get; set; } public int UserID { get; set; } } 

L'user peut être affecté à Project soit via son RoleID, soit spécifiquement par son UserID.

Je souhaite get tous les projets qui remplissent l'une des deux conditions suivantes: L' user est dans le rôle affecté au projet (collection de rôles) ou l' user est affecté directement au projet (ProjectUsers)

J'ai découvert que je ne peux pas faire deux jointures à gauche parce que "je ne peux pas aller chercher plusieurs sacs":

 ProjectRole prAlias = null; ProjectUser puAlias = null; var projects = s.QueryOver<Project>() .Left.JoinAlias(p => p.Roles, () => prAlias) .Left.JoinAlias(p => p.ProjectUsers, () => puAlias) .Where(p => p.DeletedDate == null) .And(() => puAlias.UserID == loggedUserID) Ressortingctions.Or( Ressortingctions.On(() => prAlias.RoleID).IsIn(userRoles), Ressortingctions.Where(() => puAlias.UserID == loggedUserID) ); 

J'ai essayé de le faire avec deux requêtes distinctes et futures:

 var projectsForUserRoles = s.QueryOver<Project>() .Left.JoinAlias(p => p.Roles, () => prAlias) .Where(p => p.DeletedDate == null) .And(() => prAlias.RoleID).IsIn(userRoles)) .Future(); var projectsForUser = s.QueryOver<Project>() .Left.JoinAlias(p => p.ProjectUsers, () => puAlias) .Where(p => p.DeletedDate == null) .And(() => puAlias.UserID == loggedUserID) .Future(); var projects = projectsForUserRoles.ToList(); 

Mais de cette façon, je ne reçois que les résultats de la requête projectsForUserRoles , et non de projetsForUser . Les deux requêtes fonctionnent OK séparément – le premier renvoie 3 loggings, le second 2 loggings. Ce que je voudrais get, c'est la sum de ceux (5 records) avec le résultat Distinct:

 SELECT DISTINCT p.ProjectID, p.ProjectName FROM Projects p LEFT JOIN ProjectRoles pr ON pr.ProjectID = p.ProjectID LEFT JOIN ProjectUsers pu ON pu.ProjectID = p.ProjectID WHERE p.DeletedDate IS NULL AND( pr.RoleID IN (SELECT ur.RoleID FROM UserRoles ur WHERE ur.UserID = 1) OR pu.UserID = 1 ) 

Qu'est-ce que je rate? Comment lier deux requêtes sur le même Project entité?

Avez-vous essayé de terminer le travail en memory? Pour votre cas, cela me semble raisonnable.

 using System.Linq; // ... var projects = projectsForUserRoles.Union(projectsForUser).ToList(); 

C'est ce qui suggère Najera dans son commentaire , mais pas besoin de se préoccuper de GetHascode et Equals juste pour ce cas: le cache de premier niveau vous assurera que vous obtiendrez des references identiques pour les mêmes entités.

Maintenant, il me semble étrange que la limite "plus d'un sac" entre en jeu pendant que vous filterz juste sur eux. Mais le message dit que vous allez chercher. Je ne sais pas beaucoup de requêtes et je ne peux pas vous aider à le changer pour filterr seulement, ne pas aller chercher.

Avec linq-to-nhibernate j'écrirais plutôt:

 using System.Linq; using NHibernate.Linq; // ... var projects = s.Query<Project>() .Where(p => p.DeletedDate == null) .Where( p => p.ProjectUsers.Any(pu => pu.UserID == loggedUserID) || p.Roles.Any(pr => userRoles.Contains(pr.RoleID))) .ToList();