Reputation: 3081
I have a table called Article:
-Id
-Title
-Content
-Tags (This is a comma seperated list of tags e.g. 'Sports,Italy,Ferrari')
Using entity framework i want to be able to find all articles that have certain tags.
List<Article> GetArticles(List<String> tags)
{
//do an entity framework query here to find all articles which have the tags specified
}
The returned entries should contain all the tags specified. e.g. If the input to the function was 'car','blue', then all entries with these at least these 2 tags should be returned.
I can't begin to imagine how i might implement this. I know how to achieve this using a stored procedure which is my plan b.
Upvotes: 1
Views: 6071
Reputation: 1
how to go for multiple data in column have comma separated data.
eg: Ienumerable<string> searchItems
--- it will list say A,B,C
table with column Subscribe --- having data say "E,A,R,C,B,D,H"
So we need predicate to generate query with where clause having search to be generate query as:
WHERE Subscribe LIKE'%A%' OR LIKE'%B%' OR LIKE'%C%'
currently it generated:
WHERE Subscribe LIKE'%A%' AND LIKE'%B%' AND LIKE'%C%'
when we try - searchItems.ForEach(y => query = query.Where(y => y.Subscribe.Contains(y)));
Upvotes: 0
Reputation: 205759
Since there is no construct that allows parsing inside the query, you can use the following trick
var query = db.Articles
.Where(article => tags.All(tag => ("," + article.Tags + ",").Contains("," + tag + ",")))
.ToList();
It basically does the opposite of parsing by checking if the table field contains all the passed tags by using string.Contains and Enumerable.All constructs which are both supported by the EF. Concatenating the comma at the beginning/end is needed to correctly handling the first/last tags inside the string.
Upvotes: 2
Reputation: 239430
A stored procedure is actually a good option, if not the best option, really. However, you can still achieve it with Contains
:
var articles = db.Articles.Where(m => tags.Any(t => m.Tags.Contains(t)));
What this does is basically iterate over the passed in tags and creates a query that tests whether Tags
is LIKE any of those. Bear in mind that because this is going to be a LIKE query that it's going to be sloooooowwwww, unless your Tags
column is indexed, which then also requires that be a defined length, rather than something like NVARCHAR(MAX).
Another potential issue is false matches. Let's say you have the tags, "Read" and "Reading", because this is a LIKE query, search for the "Read" tag, will return both. The only way around this, really, is to add a tag-delimiter to your data, for instance: "[Read],[Reading]". Then, you search instead of for "[Read]", instead of "Read", and you're guaranteed to only pull back the right one.
When I need to pack/unpack strings like this, I'll typically do something like:
public string Tags
{
get
{
return TagsList != null
? String.Join(",", TagsList.Select(tag => "[" + tag + "]"))
: null;
}
set
{
TagsList = !String.IsNullOrWhiteSpace(value)
? value.Replace("[", "").Replace("]", "").Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList()
: new List<string>();
}
}
[NotMapped]
public List<string> TagsList { get; set; }
That looks fairly complicated, but all that's going on is that the setter is unpacking the list of tags on the delimiter, removing the phrase-delimiting characters I chose to use, [
and ]
. The getter packs the list back into a string with all that.
This allows you to then just work with TagsList
and the string version will be persisted automatically without having to think about it. However, when querying, you will still have to query on Tags
, since that is the actual database-backed property.
Upvotes: 5
Reputation: 7562
You need a csv parser. Entity framework should only get you the field (Tags) as a string variable. The parser will then be able to split that single string into your List Tags.
Upvotes: -1