LINQ to SQL查询成功或失败基于使用外键而不是使用内置导航属性

时间:2017-12-31 14:33:48

标签: c# sql-server linq linq-to-sql linqpad

我对一个抛出Error converting data type nvarchar to numeric.异常的SQL服务器数据库进行了查询。我试图在varchar字段上使用Convert.ToDecimal,但是我尽可能地使用 数据,并且无法找到无效值。

该查询正在通过'组'过滤表格。使用p.pgKey=#的外键。但是,如果我使用导航属性并通过导航属性进行过滤,p.Group.gName='ABC'查询将起作用。

以下是查询(请注意,最初,我不知道Where翻译或Select处理中是否发生了错误,因此查询看起来很奇怪,但是可以猜测,当它工作时,它应该只返回true}的一个不同的行:

Profiles
    .Where(p =>
       p.pgKey == 237
       && !p.pPlanProfile.Value
      && Convert.ToDecimal(p.pSearch08 ?? "0") > 0
    ).Select(p =>
       Convert.ToDecimal(p.pSearch08 ?? "0") > 0
    )
    .Distinct()
    .Dump();

上述查询失败,而此查询成功:

Profiles
    .Where(p =>
       p.Groups.gName == "ABC"
       && !p.pPlanProfile.Value
       && Convert.ToDecimal(p.pSearch08 ?? "0") > 0
    ).Select(p =>
       Convert.ToDecimal(p.pSearch08 ?? "0") > 0
    )
    .Distinct()
    .Dump();

下面是一个完整的LINQPad屏幕转储,显示:

  1. 证明ABC的gKey是237。
  2. 使用pgKeyGroup.gName时,证明计算个人资料记录的简单计数相同。
  3. 使用Group.gName处理时显示查询正常工作。
  4. 使用pgKey处理时显示查询失败。
  5. LINQPad screenshot

    显然我已经使用Group.gName方法解决了我的问题,但我偶然发现了这个解决方案。任何人都知道为什么LINQ to SQL会以这种方式运行?

    注意:使用LINQPad生成的DataContext或者针对编译的.dbml DataContext运行时,我得到了相同的行为。

1 个答案:

答案 0 :(得分:0)

这两个查询将生成不同的TSQL,因此查询计划将有所不同。

我怀疑前一个查询是试图将pSearch08的某些值转换为十进制之前它会根据其他选择标准拒绝它们,而后一个查询首先执行其他选择条件,因此试图将较少数量的pSearch08值转换为十进制,因此不会尝试转换无效值。

如果是这种情况,那么假设第二个查询将始终有效并且最好修复无效数据可能是危险的。

您可以尝试

,而不是关注数据
SELECT * from Profile where ISNUMERIC(pSearch08) = 0