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