i have this in my query:
var results = (from urls in _context.Urls
join documents in _context.Documents on urls.UrlId equals documents.Documen
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 };
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(...)
)
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:
This is the resulting SQL:
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.
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.