nhibernate запрос к соединению с подзапросом, чтобы получить статистический столбец - PullRequest
10 голосов
/ 23 августа 2011

Я искал несколько часов, как это сделать, но не могу найти ничего, чтобы помочь мне.

Вот модель базы данных:

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

Может кто-нибудь помочь мне, пожалуйста? Это не обязательно должно быть с подсоединением, может быть, есть другое лучшее решение, которого мне не хватает ...

Спасибо, Космин

Ответы [ 2 ]

12 голосов
/ 23 августа 2011

Прочитав здесь сотни подобных вопросов, я нашел ответ: коррелированный подзапрос. Как это:

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

Аналогичный вопрос, на который я получил ответ, этот .

2 голосов
/ 23 августа 2011

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