Kann ich ohne mit der Where-Klausel einen benutzerdefinierten Ausdruck erstellen?
-
29-09-2019 - |
Frage
Während ich dieses Thema bereits in einer früheren Frage mit einer nativen Abfrage gelöst habe. Ich frage mich jetzt, ob es möglich ist, einen benutzerdefinierten Ausdruck zu schaffen, die ohne Verwendung der where-Klausel in einem Criteria verwendbar ist? Der Grund, warum ich will nicht die where-Klausel ist, weil Oracle connect by ... start with ...
( hier ) Erklärung. Ich folgte diese Seite meine, um loszulegen. Dies wird jedoch Code wie select * from foo where connect by start with
erzeugen ...
Hier ist, was ich verwende. Mit Blick auf, was ich kann erzeugt wird sagen, dass es die richtige Aussage erzeugt abzüglich das where-Klausel.
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 "";
}
}
Ich bin es so verwendet wird.
StartWithConnectByCriteria criterion =
new StartWithConnectByCriteria(
"parent",
"parent_value",
"child");
DetachedCriteria dc = DetachedCriteria.For<NormalUpstream>("nu")
.Add(criterion);
Ich habe das Gefühl, es hat mit dem .Add()
vom DetachedCriteria aber nicht 100% sicher zu tun. Leider kann ich nicht scheinen, viel Dokumentation über das Erstellen eines benutzerdefinierten Ausdruck zu finden.
Edit: Nun, da ich darüber nachdenke sieht aus wie ich den Holzweg bin. Zwar ist dies nicht entscheidend ist (ich habe schon eine ordentliche Umsetzung). Ich bin immer noch daran interessiert zu sehen, wie ich kann weiter NHibernate anpassen.
Edit 2: Da aus der Box NHibernate unterstützt keine Oracle-eigene Funktion, start with ... connect by
. Ich versuche, von NHibernate mehr über Verlängerung zu lernen für sie das Hinzufügen native Unterstützung. Ich bin mir bewusst, ich diese Funktion mit einem benutzerdefinierten Dialekt registrieren. Aber ich frage mich, ob es möglich ist, es als Kriterium zu implementieren, damit ich es mit meinen anderen Kriterien Abfragen verwenden kann. Der Code habe ich geschrieben funktioniert gut und schafft richtig gültige SQL, aber wenn ich hinzufügen StartWithConnectByCriteria meiner Kriterien, NHibernate werden Fragen eine Abfrage wie select this_.id from table where start with ... connect by
. Welches ist eine ungültige Abfrage, da diese Klausel gehört nicht mit dem, wo.
Dies ist die Abfrage, die ich erwarten würde für NHibernate zu erzeugen.
select
random_column
from
table
start with parent_id = 'parent_node_id'
connect by prior child_up_id = parent_id
Beachten Sie, wie es ist keine where
Klausel in dieser Abfrage. Allerdings könnte start with ... connect by
noch mit einem where clause
verwendet werden. Sie können mehr darüber lesen, wie diese Keywords arbeiten hier .
Lösung
Ich weiß nicht, ob die vorhandene NHibernate Syntax für diese erlaubt, aber es ist eine ANSI-Standard-Syntax für hierarchische Abfragen, die als nützlich erweisen können. Ich glaube, es funktioniert nur in 11R2 und oben, aber so bin ich nicht sicher, ob es für Sie geeignet ist. Siehe rekursive Subquery Refactoring für weitere Informationen .