【问题标题】:LINQ to SQL query fails using two Contains statements使用两个包含语句的 LINQ to SQL 查询失败
【发布时间】:2010-10-01 16:16:39
【问题描述】:

我有两张桌子,DH_MASTERDH_ALIASDH_MASTER 包含有关人员的信息,包括他们的姓名。 DH_ALIAS 包含有关此人的 AKA 记录。这些表由Operator 字段链接,该字段是DH_MASTER 中的主键。

用户希望通过存储在DH_MASTER 中的名称进行搜索,并搜索他们所有已知的别名。如果在 DH_MASTERDH_ALIAS 中找到任何匹配项,则应返回 DH_MASTER 实体。

我创建了下面的查询,它应该给出我描述的结果(返回任何 DH_MASTER.Name == nameDH_MASTER.DH_ALIAs(n).Name == name 所在的 DH_MASTER 行)。

如果我只使用.Contains 行中的一个,它就可以正常工作。我使用哪一个并不重要。但是当我尝试同时使用 BOTH 时执行失败。


    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 查询分析器中并在 LIKE 参数周围添加撇号,它运行得很好。事实上,即使有超过 200 万行,它也快如闪电(眨眼间)。

但是当 LINQ 查询运行时,Web 应用程序锁定了大约 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

【问题讨论】:

  • 这看起来很奇怪,因为为 LIKE 子句生成的 SQL 应该看起来像 [t0].[Name] LIKE @p0
  • 我再次查看后,查询确实有参数,但您必须检查 SQL Server 查询可视化工具中的“显示原始”框才能看到它们。

标签: sql linq-to-sql timeout contains


【解决方案1】:

这可能不合适,因为您的问题不同,但我记得我的一个程序中有一个问题: Contains() 不起作用(在我的情况下,它会在评估时抛出异常),所以也许 Contains-方法有点破。

我换了

result.Contains( x )

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

确实有效。

如果可行,你可以试试吗?至少这可能是朝着正确方向迈出的一步。

【讨论】:

  • 使用您的想法,我能够稍微重构一下我的代码。这比我的原始代码效果更好,但正如您所见,它并没有消除对 .Contains 调用的需要,因为我仍然想返回“模糊”匹配。出于某种原因,在 lambda 表达式内第二次调用 .Contains 是可行的,但在 lambda 表达式之外再次调用它是行不通的!
【解决方案2】:

Linq to sql 不直接在查询中指定值,它使用参数。你确定它直接在sql中有包含参数值吗?

无论如何,超时很可能是由死锁引起的:查询想要从被另一个(插入/更新)查询/事务锁定的表中读取行,并且该查询显然需要更长的时间才能完成。

【讨论】:

  • 您对第一部分是正确的 - 当我单击可视化工具中的“显示原始”复选框时,它会显示参数化查询。但是,除了通过每晚的 SSIS 包之外,这些表永远不会插入/更新。
猜你喜欢
  • 2017-10-17
  • 1970-01-01
  • 1970-01-01
  • 2011-11-25
  • 1970-01-01
  • 2013-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多