Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
460 views
in Technique[技术] by (71.8m points)

c# - Method 'Boolean Contains..' has no supported translation to SQL

i have this in my query:

var results = (from urls in _context.Urls
               join documents in _context.Documents on urls.UrlId equals documents.DocumentId
               let words = (from words in _context.Words
                            join hits in _context.Hits on words.WordId equals hits.WordId
                            where hits.DocumentId == documents.DocumentId
                            select words.Text).AsEnumerable<string>()

                where urls.ResolvedPath.Contains(breakedQuery, KeywordParts.Url, part) ||
                      documents.Title.Contains(breakedQuery, KeywordParts.Title, part) ||
                      documents.Keywords.Contains(breakedQuery, KeywordParts.Keywords, part) ||
                      documents.Description.Contains(breakedQuery, KeywordParts.Description, part) ||
                      words.Contains(breakedQuery, KeywordParts.Content, part) ...

and Contains extension method:

for strings

public static bool Contains(this string source, IEnumerable<string> values, KeywordParts valuePart, KeywordParts part)
    {
        if (!string.IsNullOrWhiteSpace(source))
            return source.Split(' ').AsEnumerable<string>().Contains(values, valuePart, part);
        return false;
    }

for enumerables (main method)

public static bool Contains(this IEnumerable<string> source, IEnumerable<string> values, KeywordParts valuePart, KeywordParts part)
    {
        if (source != null && source.Count() > 0 &&
            values != null && values.Count() > 0 &&
            (part == KeywordParts.Anywhere || valuePart == part))
        {
            foreach (var value in values)
            {
                var has = false;
                var none = (value.StartsWith("-"));
                string term = value.Replace("-", "");

                if (none)
                    has = source.Any(q => !q.Contains(value));
                else
                    has = source.Any(q => q.Contains(values));

                if (has)
                    return has;
            }
        }
        return false;
    }

and using Contains method throws exception NotSupportedException: Method 'Boolean Contains(String, IEnumerable`1[String], KeywordParts, KeywordParts)' has no supported translation to SQL.

actually i want to check each indexed document if have at lease one of specified conditions

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You can't just write your own methods and call them from your query expression - the query translator has no idea what that method's meant to do.

You could force the where clause to be executed in .NET after fetching the documents and words, potentially... although obviously that means fetching all the joined data from the database. Would that be okay?

To do that, you'd want something like:

var tmpQuery = (from urls in _context.Urls
                join documents in _context.Documents 
                on urls.UrlId equals documents.DocumentId
                let words = (from words in _context.Words
                             join hits in _context.Hits 
                             on words.WordId equals hits.WordId
                             where hits.DocumentId == documents.DocumentId
                             select words.Text)
                select new { urls, documents, words };

var query = from r in tmpQuery.AsEnumerable()
            let urls = r.urls.ToList()
            let words = r.words.ToList()
            let documents = r.documents.ToList()
            where urls.ResolvedPath.Contains(breakedQuery, 
                                             KeywordParts.Url, part) ||
               documents.Title.Contains(breakedQuery,
                                        KeywordParts.Title, part) ||
               documents.Keywords.Contains(breakedQuery,
                                           KeywordParts.Keywords, part) || 
               documents.Description.Contains(breakedQuery, 
                                              KeywordParts.Description, part) ||
               words.Contains(breakedQuery, KeywordParts.Content, part)
            select new { urls, words, documents };

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...