Могу ли я создать пользовательское выражение без использования предложения where?

Хотя я уже решил эту проблему в предыдущем вопросе, используя собственный запрос. Теперь мне интересно, можно ли создать пользовательское выражение, которое можно использовать в критериях, без использования предложения where? Причина, по которой я не хочу использовать предложение where, заключается в том, что Oracle connect by ... start with ... (здесь) заявление. Я следовал этому страницу, чтобы начать. Однако это сгенерирует такой код, как 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);

У меня есть ощущение, что это связано с .Add() из DetachedCriteria, но не уверен на 100%. К сожалению, я не могу найти много документации о создании пользовательского выражения.

Редактировать: теперь, когда я думаю об этом, похоже, что я лаю не на то дерево. Пока это не критично (у меня уже есть достойная реализация). Мне все еще интересно посмотреть, как я могу дополнительно настроить NHibernate.

Редактировать 2: поскольку NHibernate не поддерживает проприетарную функцию Oracle, start with ... connect by. Я пытаюсь узнать больше о расширении NHibernate, добавив для него встроенную поддержку. Я знаю, что могу зарегистрировать эти функции на собственном диалекте. Но мне интересно, можно ли реализовать его как критерий, чтобы я мог использовать его с другими запросами критериев. Код, который я разместил, отлично работает и правильно создает действительный SQL, но когда я добавляю StartWithConnectByCriteria в свои критерии, NHibernate выдает запрос, например select this_.id from table where start with ... connect by. Это недопустимый запрос, потому что это предложение не относится к тому, где.

Это запрос, который я ожидаю от 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. Подробнее о том, как работают эти ключевые слова, можно прочитать здесь.


person Mike    schedule 19.08.2010    source источник


Ответы (1)


Я не знаю, позволяет ли это существующий синтаксис NHibernate, но есть стандартный синтаксис ANSI для иерархических запросов, который может оказаться полезным. Однако я считаю, что это работает только в 11R2 и выше, поэтому я не уверен, что это полезно для вас. Дополнительные сведения см. в разделе Рефакторинг рекурсивных подзапросов. .

person Adam Hawkes    schedule 20.10.2010
comment
Я не думаю, что Criteria API поддерживает WITH. Я мог бы уйти с нами, используя HQL или собственный SQL-запрос. Спасибо. - person Mike; 25.10.2010