我可以在不使用where子句的情况下创建自定义表达式吗?

时间:2010-08-19 16:47:03

标签: oracle nhibernate connect-by nhibernate-criteria

虽然我已经使用本机查询在上一个问题中解决了这个问题。我现在想知道是否可以在不使用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的知识。我知道我可以用自定义方言注册这些功能。但我想知道是否可以将其作为Criteria实现,以便我可以将其与其他标准查询一起使用。我发布的代码工作正常并正确创建有效的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

1 个答案:

答案 0 :(得分:0)

我不知道现有的NHibernate语法是否允许这样做,但是有一种ANSI标准语法可用于分层查询,这可能非常有用。我相信它只适用于11R2及以上,所以我不确定它是否对你有用。有关详细信息,请参阅Recursive Subquery Refactoring