0

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.

3
  • 1
    If you can have multiple tags, why not hold them in a list, array or any other sort of container instead of using string manipulation? Commented Nov 5, 2013 at 8:26
  • can you show me a sample code with query? Commented Nov 5, 2013 at 8:32
  • 1
    thats no good table design. You need to normalize the table to 3rd form 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 an primary key tagid. than you just need to edited for example the one tag in tag table if it changes and it will be updated at every referencing arcticle. edit: i just recognized your not talking of tables, anyway you tagged as sql-server. look at the answer of nvoigt, that is the same what i mentioned but not with table design Commented Nov 5, 2013 at 8:34

5 Answers 5

1

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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.

Comments

0

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 ...".

Comments

0

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

2 Comments

but it has to be kept in mind, that, if any large table is being queried, the whole amount of data will be read in memory by calling ToList(). That can be inperformant.
thanks, @Dom84, of cause better approach would be to normalize the database for better suiting for working with tags
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.