【问题标题】:NHibernate Criteria generate invalid SQL for Sybase when using SubqueriesNHibernate Criteria 在使用子查询时为 Sybase 生成无效 SQL
【发布时间】:2026-01-23 12:15:01
【问题描述】:

标准:

var subQuery = DetachedCriteria.For<RecordInfo>();
    .Add(Restrictions.Eq("Property1", "some string"))
    .Add(Restrictions.EqProperty("Property2", "record.Id"))
    .SetProjection(Projections.Max("Id"));

var criteria = session.CreateCriteria(typeof(Record), "record")
    .CreateAlias("record.ListOfRecordInfo", "recordInfo")
    .Add(Subqueries.PropertyEq("recordInfo.Id", subQuery));

将为 Sybase ASE 15.5 方言生成类似的内容:

SELECT this_.Record_Id as Record1_2_3
...
FROM Record this_
INNER JOIN Record_Info Record_Info_
ON this_.Record_Id = Record_Info_.Property_2
WHERE Record_Info_.Record_Info_Id = 
(
    SELECT max(this_0_.Record_Info_Id) as y0_
    FROM Record_Info this_0_
    WHERE this_0_.Property_1 = @p0
    AND this_0_.Property_2 = this_.Record_Id
)

问题是生成的 as y0_,Sybase 不允许对我正在使用的 Sybase 版本进行子查询的别名。

如何修改我的查询以使 NHibernate 不会为子查询生成别名?

【问题讨论】:

    标签: nhibernate subquery sap-ase hibernate-criteria


    【解决方案1】:

    我们可以通过自定义 SQL 语句调整子查询的投影。所以而不是:

    var subQuery = DetachedCriteria.For<RecordInfo>(); 
        ...
        .SetProjection(Projections.Max("Id")); // instead of this
    

    我们可以这样做:

    var subQuery = DetachedCriteria.For<RecordInfo>(); 
        ...
        .SetProjection(Projections.SqlProjection(" MAX(RecordInfoId) " // use this
          , new string[] {"ID"}
          , new IType[] {NHibernate.NHibernateUtil.Int32}));
    

    我们必须使用列名,因为我们正在跳过 NHibernate Property-to-Column(IdRecordInfoId)。

    这样可以避免

    • SELECT max(this_0_.Record_Info_Id) as y0_ 替换为
    • SELECT MAX(RecordInfoId)(我们的自定义 SQL)

    【讨论】: