我能够创建一个我觉得很奇怪的LINQ语句,想看看是否有其他人有过这方面的经验。
我已将其简化为:
var x = db.Test
.Where(a => a.Field1 == Utils.CreateHash(Preferences.getValue(a.Field2)))
.FirstOrDefault();
现在这如何转化为数据库代码? LINQ不需要对每一行进行双重查询,即行a:
1) Query a.Field2 2) Return value to run Utils.CreateHash(Preferences.getValue(a.Field2)) 3) Take that value from step 2 and compare it against a.Field1 4) Repeat 1-3 until I've gone through all the rows or returned a matching row
这不是非常低效吗?或者LINQ足够智能以更好的方式运行它?注意,我实际上没有运行此代码,因此另一种可能性是运行时错误。为什么LINQ不够智能,无法检测到冲突然后让我编译它?
答案 0 :(得分:2)
由于在您尝试在DB上执行的lambda中调用Utils.CreateHash
,因此查询不会起作用 - 在该上下文中,您无法执行该方法,因为数据库上没有等效项因此查询将失败。
一般来说,第三方Linq IQuerable
提供程序(例如Linq to SQL,Linq to Entities)访问内存结构(如方法或类)的能力非常有限,因为根据经验,访问原语最多基元的值或集合将起作用。
答案 1 :(得分:1)
只是加快... ...
知道这是如何工作的一个很好的例子是写(极端情况我同意,但最好:)或浏览自定义(开源)LINQ提供程序的源代码(例如http://relinq.codeplex.com/有一个等)。
基本上(我在这里简化了一些事情),一个LINQ提供者只能“映射”到他所知道的Db(支持的SQL,函数)。
即它有一个它可以使用的标准集,除此之外,并且在框架中使用自定义方法(不转换为常量等),没有办法在'Db / SQL端'解决这个问题。
例如。使用“自定义”linq提供商(此处不是这种情况),您可以添加特定的分机号码,例如.MyCalc() - 它将被正确解析并转换为SQL等价物 - 然后你就可以使用它了。
除此之外,我认为如果我记得正确,提供者将把它作为表达式,以便在它从Db'fetch'返回查询操作时解决。或者在某些情况下抱怨它
Linq基于IQueryable - 您可以查看为其提供的SQL等价物支持的扩展方法
希望这有助于
编辑:事情是否“有效”并不重要 - 它仍然不意味着它在Db上下文中执行 - 即在大多数情况下它是不可接受的性能。 IQueryable适用于表达式(如果你看一下界面) - 并且通常在你调用或枚举时执行linq。此时,某些表达式可能会计算为可以在SQL中使用的const值,但在您的情况下则不然
最好的测试方法是测试查询生成的SQL(我认为这可能是Translate LINQ to sql statement)。
答案 2 :(得分:0)
没有
LINQ提供程序将运行一个SELECT查询,该查询选择两个字段,然后使用每个返回行的两个值执行lambda表达式。