NHibernate QueryOver与子查询连接

时间:2014-09-27 14:53:20

标签: nhibernate join orm queryover

有人知道如何使用NHibernate QueryOver生成以下sql查询吗?

选择        this_.Id为Id2_1_,        this_.name为name2_1_,        this_.rp_id为rp3_2_1_,        rtlprd1_.Id为Id3_0_,        rtlprd1_.name为name3_0_ 从        收据_    左外连接        rtl_prd rtlprd1_            on this_.rp_id = rtlprd1_.Id    左连接(SELECT ...)

按代码映射:

class Receipt
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual RtlPrd RtlPrd { get; set; }
    public virtual JoinClass JoinClass { get; set; }

}
class ReceiptMap : ClassMapping<Receipt>
{
    public ReceiptMap()
    {
        Table("receipt");
        Id(x => x.Id);
        Property(x => x.Name, m => m.Column("name"));
        ManyToOne(x => x.RtlPrd, m =>
        {
            m.Column("rp_id");
            m.Cascade(Cascade.None);
        });
        ManyToOne(x => x.JoinClass, m =>
        {
            m.Column("rp_id");
            m.Cascade(Cascade.None);
        });
    }
}
class RtlPrd
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
}
class RtlPrdMap : ClassMapping<RtlPrd>
{
    public RtlPrdMap()
    {
        Table("rtl_prd");
        Id(x => x.Id);
        Property(x => x.Name, m => m.Column("name"));
    }
}
class LnkPrdType
{
    public virtual int LptId { get; set; }
    public virtual string Name { get; set; }
}
class LnkPrdTypeMap : ClassMapping<LnkPrdType>
{
    public LnkPrdTypeMap()
    {
        Table("lnk_prd_type");
        Id(x => x.LptId, m => m.Column("lpt_id"));
        Property(x => x.Name, m => m.Column("name"));
    }
}
class LnkPrd
{
    public virtual int LpId { get; set; }
    public virtual string Name { get; set; }
    public virtual LnkPrdType LnkPrdType { get; set; }
    public virtual RtlPrd RtlPrd { get; set; }

}

class LnkPrdMap : ClassMapping<LnkPrd>
{
    public LnkPrdMap()
    {
        Table("lnk_prd");
        Id(x => x.LpId, m => m.Column("lp_id"));
        Property(x => x.Name, m => m.Column("name"));
        ManyToOne(x => x.LnkPrdType, m =>
        {
            m.Column("lpt_id");
            m.Cascade(Cascade.None);
        });
        ManyToOne(x => x.RtlPrd, m =>
        {
            m.Column("rpt_id");
            m.Cascade(Cascade.None);
        });
    }
}

class JoinClass
{
    public virtual int Id { get; set; }
}

class JoinClassMap : ClassMapping<JoinClass>
{
    public JoinClassMap()
    {
        // TODO: need add WHERE condtion in subselect
        Subselect(@"SELECT lp.lp_id
                    FROM lnk_prd lp JOIN lnk_prd_type lpt ON lp.lpt_id = lpt.lpt_id");

        Id(x => x.Id, m => m.Column("lp_id"));
    }
}

使用查询

进行示例连接
 Receipt receipt = null;
RtlPrd rtlPrd = null;
JoinClass joinClass = null;
var query = session.QueryOver(() => receipt)
    .Left.JoinAlias(() => receipt.RtlPrd, () => rtlPrd)
    .Left.JoinAlias(() => receipt.JoinClass, () => joinClass)
    .SelectList(list =>
        list.Select(() => receipt.Id))
    .List();

1 个答案:

答案 0 :(得分:0)

NHibernate是ORM工具,在映射的实体模型之上支持CRUD和强大的查询。在这种情况下,我们必须使用一些特殊的方法,这些方法在下面起草......

我们始终拥有的一种方法是使用原始SQL查询。参见:

  

以下显示如何通过AddEntity()从本机SQL查询中获取实体对象:

session
   .CreateSQLQuery("SELECT * FROM CATS")
   .AddEntity(typeof(Cat));

在这种情况下,另一个选项是创建新的“virtual”/“readonly”实体并将它们映射到调整后的views。 NHibernate支持内联视图定义,因此我们可以在不更改底层数据库的情况下对其进行管理。

这可能就是一个例子:

<class name="Cat"  lazy="true" dynamic-update="true" batch-size="25" >

    <subselect>
      SELECT CatId
      , Name
      , Age
      , ParentId
      FROM [animals].[Cat]
    </subselect>

    <cache usage="read-write" ... />
    <id name="ID" column="CatId" .. />
    <many-to-one name="Parent"...  />
    ...

正如我们所看到的,我们可以使用 <class name="cat" table="..." 来代替<subselect>我们需要的任何定义。这将作为标准实体,我们可以在此基础上创建任何类型的关系......正如我们对本机数据库视图所做的那样。

<subselect> 的内容可能是真的。上面我们看到一个表中的简单选择。但它可能是相当复杂的JOIN jam session ...