Lets say we need to select two sets from a table: "Things"
var GradeA = db.Things.Where(t=> condition1);
var GradeB = db.Things.Where(t=> !condition1 && condition2);
var DesiredList = GradeA.union(GradeB);
alternatively, we need to write a single statement to avoid union
cost:
var DesiredList = db.Things.Where(t=> condtion1 || (!condition1 && condition2));
the problem is query optimizer seems to trim the expression to condition2 only.
How to preserve the priority between condition1 and condition2
a real life example workaround is :
/// <summary>
/// Gets only first BookTag for each tag word, chooses the one of this user (if exists).
/// </summary>
/// <param name="book"></param>
/// <returns></returns>
public static IQueryable<BookTag> UniqueByTags(this IQueryable<BookTag> bookTags, User user)
{
return bookTags.GroupBy(BT => BT.TagId)
.Select(g => g.Any(bt => bt.UserId == user.Id) ?
new BookTag() { User = user, Tag = g.First().Tag, Book = bookTags.First().Book } :
new BookTag() {User = g.First().User, Tag = g.First().Tag, Book = bookTags.First().Book}
);
}
Example is getting Auto-Complete list:
str
str
and things that contain str
(no duplicates)Another Example:
Selecting ThingTags
which have 3 properties:
ThingID
UserID
TagID
we want to select only one ThingTag
for each TagID
under condition that we select the one with UserID
equals parameter if exists, otherwise select first ThingTag
for that TagID
.
Still with me ? hope so :)
Is there any reason for not writing this:
var DesiredList = db.Things.Where(t=> condition1 || condition2);
That's logically the same set of elements, after all. As it's a simpler expression, it's more likely that the query generator will get it right. Having said that, I'm surprised it's getting it wrong. Do you have a complete example you could provide?