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}
);
}
Edit:
Example is getting Auto-Complete list:
- input:
str
- output: things that start with
str
and things that containstr
(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 :)