Могу ли я создать пользовательское выражение без использования пункта «Где»?
-
29-09-2019 - |
Вопрос
Хотя я уже решил эту проблему в предыдущем вопросе, используя собственный запрос. Теперь мне интересно, можно ли создать пользовательское выражение, которое можно использовать в критериях без использования пункта «Где? Причина, по которой я не хочу, чтобы пункт о том, где орукл, Oracle connect by ... start with ...
(здесь) утверждение. Я последовал за это страница, чтобы начать. Однако это будет генерировать код, как select * from foo where connect by start with
...
Вот что я использую. Глядя на то, что генерируется, я могу сказать, что он генерирует правильное утверждение за вычетом предложения «Где».
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()
от отдельной критерии, но не на 100% уверен. К сожалению, я не могу найти много документации о создании пользовательского выражения.
РЕДАКТИРОВАТЬ: Теперь, когда я думаю об этом, похоже, что я лаю не то дерево. Хотя это не важно (у меня уже есть приличная реализация). Мне все еще интересно посмотреть, как я могу дополнительно настроить Nhibernate.
Редактировать 2: Поскольку из коробки Nhibernate не поддерживает запатентованную функцию Oracle, start with ... connect by
. Анкет Я пытаюсь узнать больше о расширении Nhibernate, добавив нативную поддержку. Я знаю, что могу зарегистрировать функцию с помощью пользовательского диалекта. Но мне интересно, можно ли реализовать его как критерии, чтобы я мог использовать его с другими запросами критериев. Код, который я опубликовал, работает нормально и правильно создает действительный SQL, но когда я добавляю в свои критерии startwithConnectBycrietia 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
. Анкет Вы можете прочитать больше о том, как работают эти ключевые слова здесь.
Решение
Я не знаю, разрешает ли существующий синтаксис Nhibernate это, но существует стандартный синтаксис ANSI для иерархических запросов, который может оказаться полезным. Я считаю, что это работает только в 11R2 и выше, однако, поэтому я не уверен, полезно ли это для вас. Видеть Рекурсивный рефакторинг подзадна за дополнительной информацией.