Question

Alors que je l'ai déjà résolu ce problème dans une question précédente à l'aide d'une requête native. Je demande maintenant s'il est possible de créer une expression personnalisée qui est utilisable dans un Criteria sans utiliser la clause where? La raison pour laquelle je ne veux pas la clause where est parce que connect by ... start with ... Oracle ( ici ) déclaration. Je suivais cette page pour obtenir mon commencé. Cependant, cela va générer du code comme select * from foo where connect by start with ...

Voici ce que je me sers. En regardant ce qui est généré, je peux dire qu'il génère la déclaration correcte moins la clause 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 "";
    }
}

Je l'utilise comme celui-ci.

StartWithConnectByCriteria criterion = 
    new StartWithConnectByCriteria(
        "parent", 
        "parent_value", 
        "child");

DetachedCriteria dc = DetachedCriteria.For<NormalUpstream>("nu")
    .Add(criterion);

Je sens qu'il a à faire avec le .Add() du DetachedCriteria mais pas à 100% sûr. Malheureusement, je ne peux pas sembler trouver beaucoup de documentation sur la création d'une expression personnalisée.

Edit: Maintenant que je pense à ce sujet semble que je suis aboyer le mauvais arbre. Bien que ce n'est pas essentiel (je l'ai déjà une mise en œuvre correcte). Je suis toujours intéressé à voir comment je peux personnaliser davantage NHibernate.

Edit 2: Depuis de la boîte NHibernate ne prend pas en charge la fonction exclusive d'Oracle, start with ... connect by. Je suis en train d'en apprendre davantage sur l'extension de NHibernate en ajoutant un support natif pour elle. Je suis conscient que je peux enregistrer les fonctions avec un dialecte personnalisé. Mais je me demande s'il est possible de la mettre en œuvre en tant que critères pour que je puisse l'utiliser avec mes autres requêtes de critères. Le code que j'affiché fonctionne bien et correctement crée SQL valide, mais quand j'ajoute StartWithConnectByCriteria à mes critères, NHibernate sera émet une requête telle que select this_.id from table where start with ... connect by. Ce qui est une requête non valide parce que cette clause ne appartiennent à l'où.

Ceci est la requête que je vous attendez pour NHibernate à générer.

select
    random_column
from
    table
start with parent_id = 'parent_node_id'
connect by prior child_up_id = parent_id

Remarquez qu'il n'y a pas de clause de where dans cette requête. Cependant, start with ... connect by pourrait encore être utilisé avec un where clause. Vous pouvez en savoir plus sur la façon dont ces mots clés fonctionnent .

Était-ce utile?

La solution

Je ne sais pas si la syntaxe NHibernate existante permet, mais il y a une syntaxe standard ANSI pour les requêtes hiérarchiques qui peuvent se révéler utiles. Je crois qu'il ne fonctionne que dans 11R2 et cependant, au-dessus, donc je ne sais pas s'il est utile pour vous. Voir récursive refactorisation sous-requête pour plus d'informations .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top