简体   繁体   中英

Entity framework and linq string comparsion issue

I have a problem with linq ..

lets see the code

I have an article class:

public calss Article
{
    public string Tag{get; set; }
}

I save each tag for article splitted by , comma.

for example : first,second,third

and when I want to get an article I want to get articles that has any common tag.

I use this query but:

var relatedArticles = 
        _db.Articles.Where(a => a.Tag
                                 .Split('،')
                                 .Any(t => article.Tag
                                                  .Split('،')
                                                  .Any(ac => ac == t)));

and I am getting this exception:

LINQ to Entities does not recognize the method 'System.String[] Split(Char[])' method

Any other way?

Update: i cant keep tags in different table because i must let user to create tags as many as he wants when he/she is inserting article. like 50 and it will be overhead to check if that tag exists or not when saving article to db.

Set your class as follows:

public class Article
{
    public List<string> Tag{get; set; }
}

I'm not 100% sure what your 2nd statement does, but you can use a.Tag.Contains() to check your values.

I think my comment could be worth as answer to your problem, so i write it down as one :)

You should think about your table / class design.

You need to normalize it because that looks like n:m reference. Keep the article in one table with a reference to a mapping table, where you reference the arcticleId and the tagId and than one table with that tags with a primary key tagId. If one Tag will change in future, you don't need to update every article, you just update that particular tag and it changes for every article.

it means that Linq to entities failed to find translation of split method that can be written as SQL query. if you want to perform split functions you have to bring the record in memory by calling ToList() , AsEnumerable() etc.

But better approach would be to create separate table for tags in your db.

Linq query would look something like this(supposing many-to-many relationship between articles and tags):

var relatedArticles = 
        _db.Articles.Where(a => a.Tags.Any(t => t.Articles.Count() > 1));
// if Article has Tag which is assigned more then to one Article then it suits us

The "a.Tag.Split('،')" is a node in the expression tree that your IQueryable is, not an actual operation. When you materialize results by calling something like ToList, the whole expression tree is translated into SQL expression before execution - this is the point of error because translator doesnt have an idea how to convert Split() method into sql statement.
As an alternative, you can retrieve all results into app, materialize them by ToList() and then do what you want with them as IEnumerables. Also, you can write a stored procedure and pass search tags array into there.
Also, maybe it will work - try to pass a simple values array (not as methods) into query so resulting sql looks like

"WHERE ... IN ...".

You can't call regular methods like string.Split() directly in Linq when working with EF, since it can't be translated to SQL.

You could append AsEnumerable() to your Where() clause to cause Linq to fetch the data, allowing you to perform operations like that on it later. Unfortunately, that will not permit you to do what you want with the list without fetching the whole list, which I'm sure you would rather avoid.

Perhaps you could do something like this instead?:

 List<string> tagsForCurrentArticle = ... // fetch this first somehow

 _db.Articles.Where(a =>  
                      tagsForCurrentArticle.Any(tag => 
                                                   a.Tag.Contains(tag)))

Note, just to be clear: This should work, but the better option, if possible, would be to move your tags out into a separate table, as others have suggested.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM