Search code examples
nhibernatequeryover

Compilation error with QueryOver and multiple SubQueries


I'm getting the following compilation error when I'm using QueryOver with a list of sub queries:

"The type arguments for method 'xxxx' cannot be inferred from the usage. Try specifying the type arguments explicitly."

Here is the code but not sure how I can correct it:

    List<QueryOver> subQueries = new List<QueryOver>();
    subQueries.Add(QueryOver.Of<Customer>().Where(...));
    subQueries.Add(QueryOver.Of<Address>().Where(...));
    subQueries.Add(QueryOver.Of<Account>().Where(...));

    var query = session.QueryOver<Customer>();

    foreach (QueryOver subQuery in subQueries)
    {
        query.WithSubquery.WhereProperty(c => c.CustomerID)
                          .In(subQuery); // this is throwing the compilation error
    }

    var result = query.Select(Projections.RowCount())
                        .FutureValue<int>()
                        .Value;

I need to do this programatically as I am generating the subQueries dynamically and don't know how many sub queries there will be. Do I need to use dynamic types or something?


Solution

  • I've managed to solve this with a little refactoring. Andrew's response gave me the idea to use .Where() (instead of .WithSubquery) and then use a Conjunction for the sub queries. The refactored code looks like this:

        Conjunction conj = new Conjunction();
        conj.Add(Subqueries.WhereProperty<Customer>(x => x.CustomerID).In(QueryOver.Of<Customer>()...));
        conj.Add(Subqueries.WhereProperty<Customer>(x => x.CustomerID).In(QueryOver.Of<AttributeValue>()...));
        conj.Add(Subqueries.WhereProperty<Customer>(x => x.CustomerID).In(QueryOver.Of<CustomerListEntry>()...));
    
        ISession session = sf.OpenSession();
        using (var tran = session.BeginTransaction())
        {
            var query = session.QueryOver<Customer>()
                                .Where(conj)
                                .Select(Projections.RowCount())
                                .FutureValue<int>()
                                .Value;
            tran.Commit();
        }
    

    I can now programatically build up and selectively apply the subqueries.