Entity Framework query a comma separated field

混江龙づ霸主 提交于 2021-01-28 21:02:48

问题


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.


回答1:


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.




回答2:


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.




回答3:


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)));




回答4:


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.



来源:https://stackoverflow.com/questions/35367621/entity-framework-query-a-comma-separated-field

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!