简体   繁体   中英

Fluent NHibernate QueryOver to select items not in another table (left join)

I have two tables:

all: id | propA | propB | someOtherColumn

hidden: id | propA | propB

and corresponding classes (Mapped, no relationship mapped yet)

I would like to get all rows from first table, minus any results which match by propA or propB property.

I managed to do it by Criteria API but would like to see how it is done with QueryOver API, if possible without subqueries but with a left excluding join.

Criteria version:

var dc1 = DetachedCriteria.For<hidden>()
    .Add(Restrictions.IsNotNull(Projections.Property("propA")))
    .SetProjection(Projections.Property("propA"));

var dc2 = DetachedCriteria.For<hidden>()
    .Add(Restrictions.IsNotNull(Projections.Property("propB")))
    .SetProjection(Projections.Property("propB"));



var query = db
    .CreateCriteria<all>()
    .Add(Restrictions.On<all>(c => c.someOtherColumn).IsLike("1"))
    .Add(Subqueries.PropertyNotIn("propA", dc1))
    .Add(Subqueries.PropertyNotIn("propB", dc2))

which gives roughly:

SELECT all.* 
FROM all
WHERE (all.someOtherColumn LIKE '1')
    and all.propA not in (SELECT hidden.propA FROM hidden WHERE hidden.propA IS NOT NULL) 
    and all.propB not in (SELECT hidden.propB FROM hidden WHERE hidden.propB IS NOT NULL)

It is ok, though it seems performance wise this would be better:

SELECT all.* 
FROM all
LEFT JOIN hidden ON all.propA = hidden.propA
LEFT JOIN hidden ON all.propB = hidden.propB
WHERE hidden.propA IS NULL
AND hidden.propB IS NULL 
AND (all.someOtherColumn LIKE '1')

If it is not possible to generate such a statement with unmapped relationships, I am open to suggestions on mapping.

It seems to me that it's not possible to create joins without mapped relationships via QueryOver. See this answer .

With subqueries you can do something like this:

All allAlias = null;
var result = Session.QueryOver(() => allAlias)
               .WhereRestrictionOn(x => x.someOtherColumn).IsLike('1')
               .WithSubquery.WhereNotExists(QueryOver.Of<hidden>()
                     .Where(h => h.propA == allAlias.propB || h.propB == allAlias.propB)
                     .Select(h => h.Id))
               .List();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM