2017-06-30 9 views
1

で2つのコレクションに参加左:NHibernateのは、私はプロジェクトの実体とProjectRoleとProjectUserエンティティを持っているQueryOverと未来

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

ユーザーは自分のRoleIDを介して、または、特に彼のユーザーIDのいずれかによってプロジェクトに割り当てることができます。 ユーザーが(役割コレクション)プロジェクトに割り当てられた役割であるかユーザーがプロジェクトに直接割り当てられている(ProjectUsers)

:私は2つの要件のいずれかを満たすすべてのプロジェクトを取得したいと思い

私は私が「複数の袋を取り出すことができない」ので、2つの左が参加することができないことを発見:

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) 
     Restrictions.Or(
      Restrictions.On(() => prAlias.RoleID).IsIn(userRoles), 
      Restrictions.Where(() => puAlias.UserID == loggedUserID) 
     ); 

私は2つの別々のクエリと未来でこれを実行しようとしました

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(); 

しかし、このように私はprojectsForUserRolesクエリ、およびないprojectsForUserから結果を取得します。両方のクエリは別々に動作します - 最初のレコードは3レコード、2レコード目は2レコードです。私が得たいものは、Distinctの結果を持つこれらの合計(5レコード)です。

私は何が欠けていますか? 2つのクエリを同じエンティティProjectにリンクするにはどうすればよいですか?

+0

あなたは 'projectsForUser.Union(projectsForUserRoles).ToList()'オーバーライドハッシュコードを試してみましたが、メソッドに等しいことがありますか? – Najera

答えて

1

作業をメモリー内で終了しようとしましたか?あなたの場合、それは私にとって賢明です。最初のレベルのキャッシュを使用すると、同じエンティティに対して同一の参照を取得します保証されます:ナヘラin his comment示唆、しかし必要はちょうどこのような場合のためにGetHascodeEqualsをオーバーライド気にしないようにするものです

using System.Linq; 

// ... 

var projects = projectsForUserRoles.Union(projectsForUser).ToList(); 

これで、フィルタリングしている間に、「複数のバッグ」の制限があります。しかし、メッセージはあなたがフェッチしていると伝えます。私はをよく知らないので、フェッチしないだけのフィルタリングのためにそれを変更する手助けはできません。

私の代わりに記述します。

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(); 
関連する問題