2011-08-22 58 views
9

我一直在寻找几个小时现在如何做到这一点,但似乎无法找到任何东西来帮助我。nhibernate queryover加入子查询得到聚合列

这里是数据库模型:

enter image description here

这是SQL查询我试图运行:

SELECT b.*, a.Assignments FROM Branch b LEFT JOIN (
     SELECT b.BranchID , COUNT(ab.BranchID) AS Assignments 
     FROM Branch b LEFT JOIN AssignmentBranch ab ON b.BranchID = ab.BranchID 
     GROUP BY b.BranchID 
    ) a ON b.BranchID = a.BranchID 

所以,基本上,我想回到分支的列表和表示该分支的分配数量的新列。

分公司模型

public class Branch : IEntity<int> 
{ 
    public virtual int ID 
    { 
     get; 
     set; 
    } 

    public virtual string Name { get; set; } 

    public virtual IList<AssignmentBranch> Assignments { get; set; } 

} 

AssignmentBranch模型

public class AssignmentBranch : IEntity<int> 
{ 
    public virtual int ID 
    { 
     get; 
     set; 
    } 

    public virtual DateTime AssignedOn { get; set; } 

    public virtual Branch Branch { get; set; } 
} 

这里是我的NHibernate的配置:

<class name="Branch" table="Branch"> 

<id name="ID" column="BranchID"> 
    <generator class="identity"></generator> 
</id> 

<property name="Name"/> 

<bag name="Assignments" cascade="none" inverse="true"> 
    <key column="BranchID"/> 
    <one-to-many class="AssignmentBranch"/> 
</bag> 

<class name="AssignmentBranch" table="AssignmentBranch"> 

<id name="ID" column="AssignmentBranchID"> 
    <generator class="identity"></generator> 
</id> 

<property name="AssignedOn" /> 
<property name="FromDate" /> 
<property name="ToDate" /> 

<many-to-one name="Assignment" column="AssignmentID" /> 
<many-to-one name="Branch" column="BranchID" /> 

我已经尝试了这种方法,但我似乎无法找到一种方法来使用QueryOver进行子查询连接。

我想是这样的:

// aliases 
Branch branch = null; AssignmentBranch assignment = null; 

var subquery = QueryOver.Of<Branch>(() => branch) 
    .Where(() => branch.Project.ID == projectID) 
    .JoinQueryOver<AssignmentBranch>(() => branch.Assignments,()=> assignment, 
            NHibernate.SqlCommand.JoinType.LeftOuterJoin) 
    .SelectList(list => list 
         .SelectGroup(x=>x.ID) 
         .SelectCount(()=>assignment.ID) 
        ); 

    var query = session.QueryOver<Branch>(()=>branch) 
        .JoinAlias(???) // how can I join with a sub-query? 
        .TransformUsing(Transformers.AliasToBean<BranchAssignments>()) 
        .List<BranchAssignments>(); 

谁能帮助我吗?它不必与子加入准确地说,也许有另一种更好的解决办法,在那里,我很想念......

谢谢 科斯明

回答

12

读取数百个类似的问题在这里后,我找到了答案:一个相关的子查询。就像这样:

// aliases 
Branch branch = null; AssignmentBranch assignment = null; 

var subquery = QueryOver.Of<AssignmentBranch>(() => assignment) 
    .Where(() => assignment.Branch.ID == branch.ID) 
    .ToRowCountQuery(); 

var query = session.QueryOver<Branch>(() => branch) 
    .Where(() => branch.Project.ID == projectID) 
    .SelectList 
    (
     list => list 
     .Select(b => b.ID) 
     .Select(b => b.Name) 
     .SelectSubQuery(subquery) 
    ) 
    .TransformUsing(Transformers.AliasToBean<BranchAssignments>()) 
    .List<BranchAssignments>(); 

类似的问题,我有我的答案是从this one

+0

确实不错。我以为你需要整个Branch对象,而不仅仅是一些属性。 – Firo

+0

我需要它来填充具有一些分支属性和分配计数的自定义实体。尽管如此,感谢您花时间回复,我认为您的回答也很有意思。 – noir

+0

这会创建一个嵌套子查询而不是左连接。我希望这会比连接执行更糟糕(尽管SQL查询优化器不断令我惊讶:-) –

2

使用QueryOver并不容易,因为目前在FROM子句中不可能有语句。有一两件事,我脑海(不是最有效的方式,我认为)

var branches = session.QueryOver<Branch>().Future(); 

var assignmentMap = session.QueryOver<BranchAssignment>() 
    .Select(
     Projections.Group<BranchAssignment>(ab => ab.Branch.Id).As("UserId"), 
     Projections.RowCount()) 
    .Future<object[]>() 
    .ToDictionary(o => (int)o[0], o => (int)o[1]); 

return branches.Select(b => new { Branch = branch, AssignmentCount = assignmentMap[branch.Id] }); 

与LINQ这将是

var branchesWithAssignementCount = session.Query<Branch>() 
    .Select(b => new { Branch = b, AssignmentCount = b.Branch.Count }) 
    .ToList();