Method 'Boolean Contains..' has no supported translation to SQL

后端 未结 5 1199
盖世英雄少女心
盖世英雄少女心 2020-12-21 21:09

i have this in my query:

var results = (from urls in _context.Urls
               join documents in _context.Documents on urls.UrlId equals documents.Documen         


        
相关标签:
5条回答
  • 2020-12-21 21:39

    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 };
    
    0 讨论(0)
  • 2020-12-21 21:39

    Another way of implementing this is to write a scalar UDF in the database that implements this functionality. Then drag that UDF onto the LINQ-to-SQL designer, which will give you access to your UDF via the data-context. Then you can use things like:

    where _context.MyContains(documents.Title, breakedQuery,
           KeywordParts.Title, part);
    

    and which will call the UDF after translation (i.e. WHERE dbo.MyContains(...))

    0 讨论(0)
  • 2020-12-21 21:42

    This is possible if you take your enumerable and add to a .ToList() prior to the .Contains(r.SomeId). I was searching on this error and originally had an ICollection with a .Contains(r.SomeId) which would throw this exception, however doing a .ToList() resolved my problem. Hope this helps someone else.

    Note: I believe there is an expression tree max to Linq2Sql... so a large list may cause you another headache. Just a thought and something to watch out for.

    This is Linq2Sql code:

    enter image description here

    This is the resulting SQL: enter image description here

    0 讨论(0)
  • 2020-12-21 21:57

    My understanding and someone please correct me if I am wrong, the problem is that when using an extension method with Linq to SQL the extension method is not executed as .NET code like the extension methods you have in your question.

    The Linq to SQL extension methods return expression trees, which the Linq to SQL engine then parses and generates the appropriate SQL query to satisfy the expression tree.

    0 讨论(0)
  • 2020-12-21 22:00

    An interesting fact about this is that I get the following error when running in .NET 4.0 on my development machine:

    "Method 'Boolean Contains(Int32)' has no supported translation to SQL."

    But it runs just fine in the production environment that utilizes .NET 3.5.

    I am guessing that it is the difference in versions between the two environments. However, it is a fact that I get the error on my development machine, but the queries DO RUN on the production environment and the LINQ query does contain the following code

    var resultParts = (
                    from l in tempDc.LineItems
                    from wo in tempDc.WorkOrders
                    where l.WorkOrderNumber == wo.WorkOrderNumber &&
                        l.OrderID == wo.OrderID &&
                        workOrderSerialNumbers.Contains(wo.SerialNumber) &&
                        l.Part.PartTypeID == (int)PartTypes.InventoryPart
                    orderby l.OrderID_WO, l.WorkOrderNumber
                    select new PickReportPartDto()
                    {...
    

    Where 'workOrderSerialNumbers is a List.

    0 讨论(0)
提交回复
热议问题