来自多个表的NHibernate Simple SELECT

时间:2017-05-21 13:01:40

标签: c# nhibernate orm

我收到了以下表格:

table X(CODE, FLAGGED, ENTRY_DATE)
table Y(ID, CODE)
table Z(ID, FIRST_NAME, LAST_NAME)

以下课程:

public class Xclass
{
    public virtual string Code { get; set; }
    public virtual bool IsFlagged { get; set; }
    public virtual DateTime EntryDate { get; set; }
}
public class Yclass
{
    public virtual string Id { get; set; }
    public virtual string Code { get; set; }
}
public class Zclass
{
    public virtual string Id { get; set; }
    public virtual string FirstName { get; set; }
    public virtual string LastName { get; set; }
}

使用以下映射:

<class name="Xclass">
    <id name="Code" />
    <property name="IsFlagged" />
    <property name="EntryDate" />
</class>

<class name="Yclass">
    <id name="Id" />
    <property name="Code" />
</class>

<class name="Zclass">
    <id name="Id" />
    <property name="FirstName" />
    <property name="LastName" />
</class>

我想做以下简单查询:

SELECT X.CODE, Z.FIRST_NAME, Z.LAST_NAME
FROM X, Y, Z
WHERE X.FLAGGED = '1'
AND X.CODE = Y.CODE
AND Y.ID = Z.ID;

我是NHibernate的新手,我读到QueryOverJoinAlias / JoinQueryOver。 但我似乎无法找到任何指向正确方向的东西。 任何反馈将不胜感激。

1 个答案:

答案 0 :(得分:1)

ORM通常用于建模类之间的关系,然后使用它们。在这里你没有建模任何。但是仍然可以执行您想要的查询:

var query = session.CreateQuery(@"
select x.Code, z.FirstName, z.LastName
    from Xclass x, Yclass y, Zclass z
    where x.IsFlagged = :flagged
        and x.Code = y.Code
        and y.Id = Z.Id")
    .SetBoolean("flagged", true);
var results = query.ToList();

这将产生一个对象数组列表。如果要在类型化类中投影它们,请使用结果转换器,例如:

var results = query
    .SetResultTransformer(
        Transformers.AliasToBean<ADtoWithPropertiesNamedAsQueryColumnAliases>())
    .List<ADtoWithPropertiesNamedAsQueryColumnAliases>();

仅在尝试执行查询时验证上述代码中的原始HQL查询。您可以使用named query在构建NHibernate会话工厂时更早地验证它。这通常可以确保您的查询在应用程序引导程序中得到验证,而不必使用代码中的原始HQL查询来测试每个功能。如果您在命名查询中出现错误,则错误的详细信息将为logged with log4net,如果您已启用它。

在你的映射下,添加:

<hibernate-mapping>
  <query name="YourQueryName"><![CDATA[
    select x.Code, z.FirstName, z.LastName
        from Xclass x, Yclass y, Zclass z
        where x.IsFlagged = :flagged
            and x.Code = y.Code
            and y.Id = Z.Id
  ]]></query>
</hibernate-mapping>

并将CreateQuery(@"...")替换为GetNamedQuery("YourQueryName")

对于使用其他查询API,在大多数情况下,您必须映射表之间的关系。此处看起来您的主键上YZ之间有one-to-one。如果确实如此,请对其进行映射,然后您就可以使用导航关系,并从关系中选择数据。

对于Code上的关系,您也可以对其进行映射,前提是Code是某个表中的唯一键,可能是X,也许是Y,或者是另一个比如W。在Code唯一的表格中,最好将其映射为natural identifier。然后,在向property-ref(以及Code)指定column时,向该表声明many-to-one关系,除非name也是Code。从该表中声明one-to-many关系,使用密钥上的property-ref指定映射在Code上完成(否则默认为主键)。
由于您的查询可以选择Y.Code而不是X.Code,并且查询api允许在where条件中使用子查询,您可以避免映射XY之间的关系使用子查询过滤Y