Reputation: 1952
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.
Upvotes: 0
Views: 936
Reputation: 864
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.
Upvotes: 1
Reputation: 19071
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.
Upvotes: 0
Reputation: 141565
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
Upvotes: 0
Reputation: 3036
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 ...".
Upvotes: 0
Reputation: 2335
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.
Upvotes: 1