使用 DetachedCriteria(首选)或 QueryOver 从表中获取列(使用内部联接)

Get columns from Tables (Using Inner Join) with DetachedCriteria (prefereable) or QueryOver

我在 NHibernate 中使用 DetachedCriteria(或使用 Session QueryOver)进行查询时遇到问题。我只需要从每个 table 中获取几列,例如 类 如下:

public class PanelaCorrida : BaseEntity
{
    public virtual Int64? CodCorrida { get; set; }

    public virtual Int64 NumLocal { get; set; }

    public virtual Boolean IdcInspecionada { get; set; }

    public virtual String Sigla { get; set; }

    public virtual String Rota { get; set; }

    public virtual Local Local { get; set; }

    public virtual Panela Panela { get; set; }
}


public class Panela : BaseEntity
{
    public Panela()
    {
        this.Local = new Local();
        this.PanelaCorridas = new List<PanelaCorrida>();
    }

    public virtual Int32 Numero { get; set; }

    public virtual Boolean IdcAtiva { get; set; }

    public virtual Int16 Status { get; set; }

    public virtual ICollection<PanelaCorrida> PanelaCorridas { get; set; }

    public virtual Local Local { get; set; }

    #endregion
}


public class Local : BaseEntity
{
    public Local()
    {
        this.PanelaCorridas = new List<PanelaCorrida>();
        this.Panelas = new List<Panela>();
    }

    #region Property

    public virtual Int32 IdLocal { get; set; }

    public virtual Int32 AreaLocal { get; set; }

    public virtual String Descricao { get; set; }

    public virtual String Codigo { get; set; }

    #endregion
}

基本上,实体 'Panela' 是 'PanelaCorrida' 的母亲(每个 Panela 可以有多个 PanelaCorrida's),但是 'PanelaCorrida' 可以在一个 Local 中。但是一个本地人也可以拥有多个 PanelaCorrida。基本上是这样的关系:

Panela 1 - N PanelaCorrida

本地 1 - N Panela

本地 1 - N PanelaCorrida

对于此查询,我需要获取数据库的 Last PanelaCorrida,但我还需要 Panela 和 Local 的信息。

到目前为止,我可以使用此 NHibernate 查询获取所有数据:

获取 'panela' 的所有活动 ID:

var panelaIdList = Session.QueryOver<Panela>()
                    .Select(c => c.Id)
                    .Where(c => c.IdcAtiva == true)
                    .List<Int64>();

获取所有活跃的 'PanelaCorrida' 的最后一个 ID(以及最后生成的 PanelaCorrida):

var corridaPanelaIdList = Session.QueryOver<PanelaCorrida>()
    .Select(
    Projections.Max<PanelaCorrida>(x => x.Id),
    Projections.Group<PanelaCorrida>(x => x.Panela)
    )
    .Where(p => p.Panela.IsIn(panelaIdList.ToArray()))
    .List<Object[]>();

现在,要获得包含所有这些 table 的所有信息的结果:

使用分离条件:

criteria = DetachedCriteria.For<PanelaCorrida>()
    .CreateAlias("Local", "L")
    .CreateAlias("Panela", "P")
    .Add(Restrictions.In("Id", corridaPanelaIdList.Select(x => x[0]).ToArray()));

会话查询结束:

var corridas = Session.QueryOver<PanelaCorrida>()
    .Where(p => p.Id.IsIn(corridaPanelaIdList.Select(x => x[0]).ToArray()))
    .List<PanelaCorrida>();

但问题是,每个 Table 我只需要几列。使用 NHibernate,我尝试使用 Projections,使用 QueryOver,我尝试使用 SelectList,但每次它们都会生成错误(找不到 属性 of ...),或者它们不会填充实体结果。

我怎样才能做到这一点?

注意:这是我的第一个查询(在 SQL 中):

select cd.num_panela_corrida, cd.num_panela, p.numero, l.num_local from scp_panela_corrida cd  
inner join scp_panela p on p.num_panela = cd.num_panela 
inner join scp_local l on l.num_local = cd.num_local and cd.num_panela_corrida
in (
    select 
        max( c.num_panela_corrida) as num_panela_corrida 
    from 
        scp_panela_corrida c 
    inner join
        scp_panela p on p.num_panela = c.num_panela
        and p.num_panela in (
            select 
                num_panela 
            from 
                scp_panela 
            where 
                idc_ativa = 1
        ) group by c.num_panela ) order by cd.num_panela_corrida desc

但客户不想使用存储过程或 HQL。

欢迎任何帮助。

通过以下代码解决(由 Radim Kohler 的 link 提供)。

Radim,如果你愿意,请用提供的 link 回答这个问题,我会接受它作为答案。感谢您的帮助。

Panela panela = null;
Local local = null;

var query = session.QueryOver<PanelaCorrida>()
    .JoinAlias(c => c.Panela, () => panela)
    .Where (c => c.Id.IsIn(corridaPanelaIdList.ToArray()))
    .SelectList(list => list
    .Select(c => c.Id))
    .Select(c => c.CodCorrida)
    .Select(Projections.Property(() => panela.Id).As("Panela.Id"))
    .Select(Projections.Property(() => panela.IdcAtiva).As("Panela.IdcAtiva"))
    .TransformUsing(Transformers.AliasToBean(typeof(PanelaCorrida)));

不知道这是否是最好的方法,但它奏效了。我们将使用 QueryOver/DetachedCriteria 分析最佳方法,但就目前而言,这很有效。

注意:我删除了一些列,只是为了解释它是如何工作的。

再次感谢。