2011-05-04 44 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