Philipp
Philipp

Reputation: 659

QueryOver: select ... where property in (...)

I try to use queryover to represent the following sql:

select * from Table1 t1 where t1.foreign_key in (select t2.Id from Table2 t2 where (...))

So I created a subquery for the inner select statement like this:

 var sq = QueryOver.Of<Table2>().Where(...).Select(c => c.Id);

However when I cannot use this subquery in the following query:

var query = QueryOver.Of<Table1>().WithSubquery.
 WhereProperty(t1 = t1.foreign_key).In(contactSubQuery);

I think the problem is that QueryOver expects a subquery over Table1 instead of Table2 in contactSubQuery, but then I cannot access the required properties of Table2. In How do I express a query containing a WHERE..IN subquery using NHibernate's QueryOver API? a similar problem is addressed (using JoinAlias), but I cannot see how to apply that solution for my case. Thanks for any help!

SOLUTION:

Thanks alot @Radim, you were almost right. I was already using

Queryover.Of<T>() 

in the query but the problem was that I was assigning it to a IQueryOver variable (since we have a no var-keyword styleguide in our company). After I assigned it to var it compiled. Since I did not expect this to cause the problem at all I simplified every variable to var in the question, so the posted code should actually already have worked lol... I checked the type and simply changed the query to (in accordance with the no-var rule):

QueryOver<Table1> = QueryOver.Of<Table1>()
        .WithSubquery
           .WhereProperty(t1 => t1.foreign_key)
           // won't compile, because passed is IQueryOver<T,T>, 
           // not the QueryOver<U>   
           .In(subquery)

where before I had...

IQueryOver<Table1, Table1> = ...

Again, thanks alot for the help!

Upvotes: 3

Views: 1688

Answers (1)

Radim K&#246;hler
Radim K&#246;hler

Reputation: 123861

You are almost there, just the syntax is not like this:

var query = QueryOver.Of<Table1>().WithSubquery.
    WhereProperty(t1 = t1.foreign_key).IsIn(contactSubQuery);

but:

 // subquery "sq"
 var sq = QueryOver.Of<Table2>().Where(...).Select(c => c.Id); 
 var query = QueryOver.Of<Table1>()
            .WithSubquery
               .WhereProperty(t1 => t1.foreign_key)
               .In(sq) // instead of .IsIn(contactSubQuery)
            ...

Because .IsIn() is a general extension method:

/// <summary>
/// Apply an "in" constraint to the named property
///             Note: throws an exception outside of a QueryOver expression
/// 
/// </summary>
public static bool IsIn(this object projection, ICollection values);

while .In() is the method of the returned result "QueryOverSubqueryPropertyBuilderBase" (the result of the .WhereProperty() call)

Also, be sure, that the passed argument into .In(subquery) is a QueryOver.Of<T>(). For example this is wrong:

var subquery = session.QueryOver<T>(); // it is named subquery
// but it is not of a type QueryOver<T>, but of a type
// IQueryOver<T, T>
// which is not what is expected here

 var query = QueryOver.Of<Table1>()
            .WithSubquery
               .WhereProperty(t1 => t1.foreign_key)
               // won't compile, because passed is IQueryOver<T,T>, 
               // not the QueryOver<U>   
               .In(subquery)
            ...

And that will produce the:

Error 1 The type arguments for method 'NHibernate.Criterion.Lambda.QueryOverSubqueryBuilderBase<NHibernate.IQueryOver<>.... cannot be inferred from the usage. Try specifying the type arguments explicitly.

Upvotes: 3

Related Questions