Сбой запроса LINQ to SQL с использованием двух операторов Contains - PullRequest
2 голосов
/ 15 января 2009

У меня есть две таблицы, DH_MASTER и DH_ALIAS. DH_MASTER содержит информацию о человеке, включая его имя. DH_ALIAS содержит записи АКА о человеке. Таблицы связаны полем Operator, которое является первичным ключом в DH_MASTER.

Пользователи хотят искать по имени, хранящемуся в DH_MASTER, а также искать по всем известным псевдонимам. Если какие-либо совпадения найдены либо в DH_MASTER, либо DH_ALIAS, то должна быть возвращена сущность DH_MASTER.

Я создал запрос ниже, который должен дать результаты, которые я описал (вернуть все строки DH_MASTER, где DH_MASTER.Name == name или DH_MASTER.DH_ALIAs(n).Name == name).

Работает нормально, если я использую только ОДИН из .Contains строк. Неважно, какой я использую. Но выполнение не удается, когда я пытаюсь использовать ОБА одновременно.


    qry = From m In Context.DH_MASTERs _
          Where (m.Name.Contains(name)) _
              OrElse ((From a In m.DH_ALIAs _
                       Where a.Name.Contains(name)).Count() > 0) _
          Select m

Запрос LinqToSQL оценивается следующим кодом SQL (как показано в визуализаторе запросов SQL Server)


SELECT [t0].[Operator], [t0].[Name], [t0].[Version]
FROM [DHOWNER].[DH_MASTER] AS [t0]
WHERE ([t0].[Name] LIKE %smith%) OR (((
    SELECT COUNT(*)
    FROM [DHOWNER].[DH_ALIAS] AS [t1]
    WHERE ([t1].[Name] LIKE %smith%) AND ([t1].[Operator] = [t0].[Operator])
    )) > 0)

РЕДАКТИРОВАТЬ: если установить флажок «Показать оригинал» в визуализаторе запросов, откроется параметризованный запрос, как и ожидалось, поэтому этот блок текста ниже следует игнорировать.

Я не знаю, является ли это проблемой или нет, но `.Contains` оценивает выражение` LIKE` (что я и ожидаю), но параметр не заключен в апострофы.

Интересно то, что если я скопирую / вставлю SQL-запрос в SQL 2005 Query Analyzer и добавлю апострофы вокруг параметров LIKE, он будет работать нормально. На самом деле, это молниеносно (мгновение ока) даже с более чем 2 миллионами строк.

Но когда выполняется запрос LINQ, веб-приложение блокируется примерно на 31 секунду, прежде чем оно окончательно завершается с этой ошибкой на gv.DataBind: Exception has been thrown by the target of an invocation.

С этим внутренним исключением: Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.

Кто-нибудь знает, почему это происходит и как можно обойти это поведение? Это сводит меня с ума, потому что сгенерированный LinqToSql SQL работает нормально в анализаторе запросов!

Обновление:

Я реорганизовал свой код на основе техник ответа. Это работает!

qry = From m In qry _
 Where m.Name.Contains(name) OrElse _ 
 m.DH_ALIAs.Any(Function(aliasRec) aliasRec.Name.Contains(name)) _ 
Select m

Ответы [ 2 ]

4 голосов
/ 23 мая 2009

Это может быть неуместно, поскольку ваша проблема в другом, но я помню проблему в одной из моих программ: Contains () не будет работать (в моем случае это вызовет исключение при оценке), поэтому, возможно, Contains метод немного сломан.

я заменил

result.Contains( x )

с

result.Any( p => p == x )

который сработал.

Можете ли вы попробовать, если это работает? По крайней мере, это может быть шаг в правильном направлении.

0 голосов
/ 16 января 2009

Linq to sql не указывает значения непосредственно в запрос, он использует параметры. Вы уверены, что он содержит значение параметра содержит непосредственно в sql?

В любом случае тайм-аут, вероятно, вызван тупиком: запрос хочет прочитать строку в таблице, которая заблокирована другим (вставкой / обновлением) запросом / транзакцией, и этот запрос, очевидно, требует больше времени для завершения.

...