Родительский идентификатор подзапроса в NHibernate QueryOver - PullRequest
0 голосов
/ 16 декабря 2011

Я пытаюсь понять, как это может работать.То, что я хотел бы иметь, это иметь все деревья из данного списка идентификаторов, в которых нет гнилых яблок.Выглядит просто, но я новичок в NHibernate, не очень хорош в SQL, и, как вы можете видеть, я застрял.

Я написал этот код здесь:

Tree treeitem = null;

QueryOver<Apple> qapple = QueryOver.Of<Apple>()
    .Where(x => (!x.IsRotten))
    .And(Restrictions.IdEq(Projections.Property<Tree>(y => y.Id)))
    // Or this one...
    //.And(Restrictions.EqProperty(
    //     Projections.Property<Apple>(y => y.Tree.Id),
    //     Projections.Property<Tree>(y => y.Id)))
    .Select(x => x.Id);

return this.NHibernateSession.QueryOver<Tree>()
    .Where(x => x.Id.IsIn(ListOfTreeId))
    .WithSubquery.WhereExists<Apple>(qapple)
    .SelectList(list => list
        .Select(z => z.Id).WithAlias(() => treeitem.Id)
        .Select(z => z.Name).WithAlias(() => treeitem.Name)
        .Select(z => z.Type).WithAlias(() => critem.Type)
    .TransformUsing(Transformers.AliasToBean<Tree>())
    .List<T>();

И псевдоSQL, который я получаю, выглядит примерно так:

SELECT id, name, type FROM trees WHERE id IN (1, 2, 3)
AND EXIST(SELECT id FROM apples WHERE NOT rotten AND apples.idtree = apples.id)

Как вы можете видеть, есть проблема с подзапросом, который использует тот же Id таблицы вместо чего-то вроде этого:

EXIST(SELECT id FROM apples WHERE NOT rotten AND apples.idtree = tree.id)

I 'м немного потерян на самом деле.Может быть, есть другой способ создать это.Любая помощь приветствуется, спасибо.

1 Ответ

3 голосов
/ 16 декабря 2011

Я не уверен, почему вы используете resulttransformer, когда тип возвращаемого значения совпадает с типом запроса

return NHibernateSession.QueryOver<Tree>()
    .Where(t => t.Id.IsIn(ListOfTreeId))
    .JoinQueryOver<Apple>(t => t.Apples)
        .Where(a => !a.IsRotten)
    .List();

Обновление: компилятор выбирает ICollection<Apple>, в то время как он действительно должен выбрать Apple для этого укажитеуниверсальный аргумент в JoinQueryOver явно

Update2: чтобы получить их уникальными

opt 1)

...
    .SetResultTransformer(Transformers.DistinctRootEntity());
    .List();

opt 2)

Tree treeAlias = null;

var nonRottenApples = QueryOver.Of<Apple>()
    .Where(a => !a.IsRotten)
    .Where(a => a.Tree.Id == treeAlias.Id)
    .Select(x => x.Id);   <- optional

return NHibernateSession.QueryOver(() => treeAlias)
    .Where(t => t.Id.IsIn(ListOfTreeId))
    .WithSubquery.WhereExists(nonRottenApples)
    .List();
...