Combine / Merge IQueryable or converting Queryover to IQueryable

1,935 views
Skip to first unread message

jmer...@gmail.com

unread,
Feb 26, 2016, 6:35:56 AM2/26/16
to nhusers
Hi all,
is there a possibility to combine several IQueryable without execute the query?

Pseudocode:
var q1 = (IQueryable<Person>).....;
var q2 = (IQueryable<Person>).....;


var q = q1.Union(q2);

or

SELECT *
FROM Table1
WHERE id IN
  (Result ids of IQueryable1)
OR
  (Result ids of IQueryable2)

I achieved a solution by using Disjunction of Queryover. As result I need an IQueryable without the query has been executed. So a solution can also be if it is possible to convert IQueryover to IQueryable.

Thanks in advance

Oskar Berggren

unread,
Feb 26, 2016, 6:39:38 AM2/26/16
to nhu...@googlegroups.com
var q1 = from p in Person
            where whatever
            select p.id;


var q2 = from p in Person
            where whatever
            select p.id;


var qC = from p in Person
            where q1.Contains(p.id) || q2.Contains(p.id)
            select p;

q1 and q2 will be used as subqueries when the SQL is formed.

/Oskar



--
You received this message because you are subscribed to the Google Groups "nhusers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nhusers+u...@googlegroups.com.
To post to this group, send email to nhu...@googlegroups.com.
Visit this group at https://groups.google.com/group/nhusers.
For more options, visit https://groups.google.com/d/optout.

jmer...@gmail.com

unread,
Feb 29, 2016, 9:05:41 AM2/29/16
to nhusers
Hi Oskar,
thanks for your response. Sorry, I forgot one thing to mention.
In the part of code where I need to combine the IQueryable I have got some external objects in a list which provide methods which return the IQueryable to combine.
So I have s.th. like this:

foreach(var subquery in listOfIQueryablePerson)
{
  combinedIQueryable = from p allPersons
                                    where subquery.Contains(p.id) || combinedIQueryable.Contains(p.id);
}

The code above fits my requirements but it is not very nice and hasn't a good performance. Is there any other solution for that?

Thanks

Gunnar Liljas

unread,
Feb 29, 2016, 9:29:41 AM2/29/16
to nhu...@googlegroups.com
You could use a PredicateBuilder (LinqKit)

var predicate=PredicateBuilder.False<Person>();

foreach(var subquery in listOfIQueryablePerson)
{
  predicate = predicate.Or(p=>subquery.Contains(p.id))
}

var combinedIQueryable = allPersons.Where(predicate);

jmer...@gmail.com

unread,
Mar 1, 2016, 11:21:43 AM3/1/16
to nhusers
Thank you Gunnar. That's a good idea. There is only one thing which does not work yet. The two (or more) IQueryable are not combined via "OR" but via "AND"

Now:

SELECT *
FROM bla as b
WHERE b.Value = 20
       and (1 /* @p3 */ = 1
             or b.Id in (SELECT ....)


But it should:

SELECT *
FROM bla as b
WHERE b.Value = 20
       OR (1 /* @p3 */ = 1
             or b.Id in (SELECT ....)


This condition is created by PredicateBuilder.True<Class>() 
1 /* @p3 */ = 1


Code:
var predicate = PredicateBuilder.True<Class>();
predicate = predicate.Or(p => object.ExtendQuery().Select(x => x.Id).Contains(p.Id));
var combinedIQueryable = allUserNotes.Where(predicate);

Gunnar Liljas

unread,
Mar 1, 2016, 11:57:17 AM3/1/16
to nhu...@googlegroups.com
But is that all? In your previous example you hade multiple expressions in listOfIQueryablePerson. If that's not the case, a predicate builder may be unnecessary.

You can't use  PredicateBuilder.True<Class>() and predicate.Or, since if you do the expression will always evaluate to true. Use  PredicateBuilder.False<Class>();

/G

Oskar Berggren

unread,
Mar 1, 2016, 12:07:06 PM3/1/16
to nhu...@googlegroups.com
He means the AND versus OR immediately after "b.Value = 20" - since the LINQ for that isn't shown I assume it was inserted in the allUserNotes query earlier with a different Where() call. There is always AND between all Where()-calls.

/Oskar

Gunnar Liljas

unread,
Mar 1, 2016, 12:11:20 PM3/1/16
to nhu...@googlegroups.com
Ok, but this predicate

var predicate = PredicateBuilder.True<Class>();
predicate = predicate.Or(p => object.ExtendQuery().Select(x => x.Id).Contains(p.Id));
var combinedIQueryable = allUserNotes.Where(predicate);

will always evaluate to true

Oskar Berggren

unread,
Mar 1, 2016, 12:27:58 PM3/1/16
to nhu...@googlegroups.com
Yes, there is two remaining problems.

/Oskar
Reply all
Reply to author
Forward
0 new messages