I have a method which takes an array of strings as parameter and queries against a collection property which is also a collection of strings. If that property has one of the values inside the string array passed as parameter, it should be returned.
Here is my code:
public IEnumerable<BlogPost> GetAll(string[] tags,
bool includeUnapprovedEntries = false) {
foreach (var tag in tags) {
foreach (var blogPost in GetAll(includeUnapprovedEntries).
ToList().Where(x => x.Tags.Any(t => t == tag))) {
yield return blogPost;
}
}
}
Note:
Here is the complete code:
This does the job but it just doesn't seem right. I could have made this better with some extension methods but couldn't figure out what would do the trick and make this implementation right.
Any idea?
How about this:
public IEnumerable<BlogPost> GetAll(string[] tags,
bool includeUnapprovedEntries = false) {
return GetAll(includeUnapprovedEntries)
.Where(x => x.Tags.Any(t => tags.Contains(t));
}
You may want to call ToList()
to materialize the result. Note that this will (hopefully!) result in an IN
query in SQL; if you have a large number of tags, I wouldn't be surprised if that failed. (I don't know how the Entity Framework handles that situation.) I believe it should be okay with smaller numbers of tags though.
Note that whether or not this is supported may depend on the version of the entity framework you're using; I seem to remember that some transformations like this (using Contains
on a "local" collection) to translate to IN in SQL) have improved over time. Make sure you develop against the same version you'll be deploying against :)
GetAll
(yep, it is a really bad approach but I couldn't figure out the other way) and does the query against that. So, it is mostly Linq to Objetcs - tugberk 2012-04-04 07:19
tags
to a HashSet<string>
first, at least if there are going to be quite a few of them to match against. That will make each match simpler - Jon Skeet 2012-04-04 07:21
HashSet
is something that allows me to query against SQL Server in this situation since the data type inside my SQL table is just NVARCHAR
. Also, I am sure that my current implementation will result a bottleneck in my application as the data grows because I am getting the whole data at once and query against those inside the memory but it is a different topic than this question's - tugberk 2012-04-04 07:25
HashSet
would just make the in-memory processing simpler. As you say, sorting out your design so that you can perform the query in SQL is probably a different matter : - Jon Skeet 2012-04-04 07:28
FK
to BlogPosts table would be better. That way, I may generate an IN
query with your above approach - tugberk 2012-04-04 07:31