2011-05-04 39 views
3

我有一個多對多的關係,我試圖查詢。我的問題與Phillip Haydon的here詳述的問題非常相似,所以我將寬鬆地借用他的圖表和解釋。NHibernate的查詢何處在多對多

菲利普有工作和角色之間的下列許多一對多的關係(抱歉,我不能插入圖片還):
data schema

菲利普需要查詢其沒有分配給作業的所有角色。他的解決方案如下:

Role roleAlias = null; 

var existing = QueryOver.Of<JobRole>() 
        .Where(x => x.Job.JobId == jobId) 
        .And(x => x.Role.RoleId != roleId) 
        .And(x => x.Role.RoleId == roleAlias.RoleId) 
        .Select(x => x.Role); 

result = Session.QueryOver<Role>(() => roleAlias) 
      .Where(x => x.IsEnabled) 
      .WithSubquery.WhereNotExists(existing) 
      .OrderBy(x => x.Name).Asc 
      .List(); 

這是非常有幫助的,但看起來在這個解決方案中每個表都有一個實體;工作,工作角色和角色。 JobRole既有工作又有角色。大概是這樣的:

public class Job 
{ 
    public int JobId {get;set;} 
    public string Name {get; set;} 
    public bool IsEnabled {get;set;} 
    public bool IsDefault {get;set;} 
} 

public class Role 
{ 
    public int RoleId {get;set} 
    public string Name {get;set} 
    public bool IsEnabled {get;set} 
    public string RoleType {get;set} 
} 

public class JobRole 
{ 
    public Job Job {get;set} 
    public Role Role {get;set;} 
} 

這種衝突與我已經看到了很多建模到多關係的格局,特別是形成了鮮明的建築實例,從這裏諮詢。在這些例子和我的例子中,我只有兩個類,工作和角色。這樣的事情:

public class Job 
{ 
    public int JobId {get;set;} 
    public string Name {get; set;} 
    public bool IsEnabled {get;set;} 
    public bool IsDefault {get;set;} 
    public IList<Role> Roles {get;set;} 
} 

public class Role 
{ 
    public int RoleId {get;set} 
    public string Name {get;set} 
    public bool IsEnabled {get;set} 
    public string RoleType {get;set} 
    public List<Job> Jobs {get;set;} 
} 

在我的情況,我需要找到所有隻有角色的工作。我已經試過這樣的事情

Job job = null; 
    Role role = null; 

    var jobs = Session.QueryOver(() => job) 
        .WithSubquery 
        .WhereExists(
          QueryOver.Of(() => role) 
          .JoinAlias(() => role.Jobs,() => job)) 
        .List().ToList(); 

但NHibernate的規定,如果一個人沒有提供,這對我來說很有意義投影在WhereExists選擇和抱怨。

用我的模型甚至可以用WhereExists做一個QueryOver子查詢?

在此先感謝。

回答

7
var jobs = session 
    .QueryOver<Job>() 
    .WhereRestrictionOn(j => j.Roles) 
     .IsNotEmpty 
    .List(); 

映射的工作:

public class Job 
    { 
     public virtual int ID { get; set; } 
     public virtual string Name { get; set; } 
     public virtual IList<Role> Roles { get; set; } 
    } 

和映射

<class name="Job"> 
     ... 
     <bag name="Roles" table="JobRoleMap" fetch="join" lazy="false" > 
      <key column="JobID" /> 
      <many-to-many column="RoleID" class="Role" />    
     </bag> 
    </class> 

在我的情況下產生下面的SQL(美化):

SELECT j.ID, 
     j.Name, 
     roles.JobID, 
     r.ID, 
     r.Name 
FROM Job j 
     left outer join JobRoleMap roles 
     on j.ID = roles.JobID 
     left outer join Role r 
     on roles.RoleID = r.ID 
WHERE exists (select 1 
       from JobRoleMap 
       where j.ID = JobID) 

,並只返回與角色的工作正如你想要的

+1

完美地工作,謝謝。 – 2011-05-05 13:46:19