1

我一直在尝试解决 VB.NET 和它喜欢生成的表达式树的一个小问题。

我有一个简单的测试...

Public Sub ActiveRecord_Find_By_NonKey_Returns_123()

  Dim orders = Order.Find(Function(item As Order) item.EmployeeID = 1)

  Assert.Equal(Of Integer)(123, orders.Count)

End Sub

人们会期望它可以工作,但该item.EmployeeID = 1位存在问题,这只是 VB.NET 的问题,而不是 C# 的问题。VB.NET 喜欢巧妙地使用它编译的表达式树,因为它可以item.EmployeeID为空!(阅读与此相关的博客

问题是表达式被表达式节点item.EmployeeID = 1包裹。Convert此时 TSql 生成器完全丢失并创建以下WHERE子句。

WHERE ([t0].[EmployeeID] = 1) <> 0

该片段在数据库上执行时往往会失败。

所以这似乎是 SubSonic 中的一个错误。不幸的是,试图弄清楚如何/在哪里修复它让我很头疼!


不过它确实变得更有趣了。

Public Sub ActiveRecord_Find_By_NonKey_Returns_123_Linq()

  Dim orders = From item In Order.All Where item.EmployeeID = 1 Select item

  Assert.Equal(Of Integer)(123, orders.Count)

End Sub

但它的WHERE条款是...

WHERE COALESCE(CASE WHEN (([t0].[EmployeeID] = 1)) THEN 1 ELSE 0 END, 0) <> 0

好吧,这似乎不是最理想的!但至少它有效。

最后,在阅读了博客条目后,似乎可以解决上面的原始示例。在 VB.NET 中使用新的合并运算符 (If)...

Public Sub ActiveRecord_Find_By_NonKey_Returns_123_Fix()

  Dim orders = Order.Find(Function(item As Order) If(item.EmployeeID, 0) = 1)

  Assert.Equal(Of Integer)(123, orders.Count)

End Sub

这产生了这个WHERE条款......

WHERE (COALESCE([t0].[EmployeeID], 0) = 1)

一个稍微更简洁的查询,尽管使用ISNULLCOALESCE? 也许只是在跨 SQL 版本的兼容性方面。


基本上,我希望第一个示例按原样工作。我还希望第二个示例继续工作,但生成更清晰的 SQL。

我想自己解决这个问题,但除了意识到我在 VB.NETs 表达式树生成方面存在一些问题之外,还没有走得太远。

4

0 回答 0