【问题标题】:Can I create a custom expression without using the where clause?我可以在不使用 where 子句的情况下创建自定义表达式吗?
【发布时间】:2010-08-19 16:47:02
【问题描述】:

虽然我已经在上一个问题中使用本机查询解决了这个问题。我现在想知道是否可以在不使用 where 子句的情况下创建可在 Criteria 中使用的自定义表达式?我不想要 where 子句的原因是 Oracle 的 connect by ... start with ... (here) 语句。我跟着this 页面开始我的工作。但是,这会生成类似select * from foo where connect by start with...

这是我正在使用的。查看生成的内容,我可以说它正在生成正确的语句减去 where 子句。

public class StartWithConnectByCriteria : AbstractCriterion
{
    public StartWithConnectByCriteria(string parentName, string parentValue, string childName)
    {
        ParentName = parentName;
        ParentValue = parentValue;
        ChildName = childName;
    }

    public string ParentName { get; set; }
    public string ParentValue { get; set; }
    public string ChildName { get; set; }
    public IProjection P { get; set; }

    public override IProjection[] GetProjections()
    {
        if(P != null)
        {
            return new IProjection[] {P};
        }
        return null;
    }

    public override TypedValue[] GetTypedValues(ICriteria criteria, ICriteriaQuery criteriaQuery)
    {
        return
            CriterionUtil.GetTypedValues(criteriaQuery, criteria, P, ParentName, ParentValue.ToString());
    }

    public override SqlString ToSqlString(ICriteria criteria, ICriteriaQuery criteriaQuery,
                                          IDictionary<string, IFilter> enabledFilters)
    {
        var sqlBuilder = new SqlStringBuilder();
        SqlString[] parentColumnNames = CriterionUtil.GetColumnNames(ParentName,
                                                               P, criteriaQuery,
                                                               criteria, enabledFilters);
        SqlString parentColumnName = parentColumnNames[0];

        SqlString[] childColumnNames = CriterionUtil.GetColumnNames(ChildName,
                                                   P, criteriaQuery,
                                                   criteria, enabledFilters);
        SqlString childColumnName = childColumnNames[0];

        criteriaQuery.AddUsedTypedValues(GetTypedValues(criteria, criteriaQuery));
        sqlBuilder
            .Add("start with " + parentColumnName + " = '" + ParentValue + "'")
            .Add(" connect by prior " + childColumnName + " = " + parentColumnName);

        return sqlBuilder.ToSqlString();
    }

    public override string ToString()
    {
        return "";
    }
}

我就是这样用的。

StartWithConnectByCriteria criterion = 
    new StartWithConnectByCriteria(
        "parent", 
        "parent_value", 
        "child");

DetachedCriteria dc = DetachedCriteria.For<NormalUpstream>("nu")
    .Add(criterion);

我感觉它与 DetachedCriteria 中的 .Add() 有关,但不是 100% 确定。不幸的是,我似乎找不到太多关于创建自定义表达式的文档。

编辑:现在我想它看起来好像我在叫错树。虽然这并不重要(我已经有了一个不错的实现)。我仍然有兴趣了解如何进一步自定义 NHibernate。

编辑 2:由于开箱即用的 NHibernate 不支持 Oracle 的专有功能start with ... connect by。我正在尝试通过添加对 NHibernate 的本机支持来了解有关扩展 NHibernate 的更多信息。我知道我可以使用自定义方言注册这些功能。但我想知道是否可以将它作为标准来实现,以便我可以将它与我的其他标准查询一起使用。我发布的代码工作正常并且正确地创建了有效的 SQL,但是当我将 StartWithConnectByCriteria 添加到我的条件时,NHibernate 将发出一个查询,例如select this_.id from table where start with ... connect by。这是一个无效的查询,因为该子句不属于 where。

这是我希望 NHibernate 生成的查询。

select
    random_column
from
    table
start with parent_id = 'parent_node_id'
connect by prior child_up_id = parent_id

注意这个查询中没有where 子句。但是,start with ... connect by 仍可与where clause 一起使用。您可以阅读更多关于这些关键字如何工作的信息here

【问题讨论】:

    标签: oracle nhibernate connect-by nhibernate-criteria


    【解决方案1】:

    我不知道现有的 NHibernate 语法是否允许这样做,但是对于分层查询有一个 ANSI 标准语法可能证明是有用的。但是,我相信它仅适用于 11R2 及更高版本,因此我不确定它是否对您有用。请参阅Recursive Subquery Refactoring 了解更多信息。

    【讨论】:

    • 我认为 Criteria API 不支持 WITH。我也许可以使用 HQL 或原生 SQL 查询摆脱我们的束缚。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2017-03-15
    • 2013-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多