Linq to SQL和Linq to Objects查询是否相同?

6
如果我们将DataContext抽象出来,那么L2S和L2O查询是否相同?我已经有一个可以证明这一点的工作原型,但它非常简单,不知道是否能够应对更高级的查询。有人知道吗?
3个回答

10
不,它们不相同。
LINQ对对象的查询操作是针对IEnumerable<T>集合的。查询通过迭代集合并执行一系列方法(例如ContainsWhere等)来处理集合中的项目。
LINQ对SQL的查询操作是针对IQueryable<T>集合的。编译器将查询转换为表达式树,然后将该表达式树翻译成SQL,并传递给数据库。
很常见的情况是,LINQ对SQL会抱怨某个方法无法被翻译成SQL,即使该方法在LINQ对对象的查询中完全正常。(在其他情况下,您可能不会看到异常,但LINQ对对象和LINQ对SQL之间的查询结果可能存在细微差异。)
例如,这个简单的查询会导致LINQ对SQL出错,而LINQ对对象则没有问题:
var query = from n in names
            orderby n.LastName.TrimStart(',', ' ').ToUpper(),
                    n.FirstName.TrimStart(',', ' ').ToUpper()
            select new { n.FirstName, n.LastName };

(通常可以绕过这些限制,但事实上你不能保证任何任意的LINQ to Objects查询都能作为LINQ to SQL查询工作,这告诉我它们不是相同的!)


当然可以,但是就像我所说的,如果我们将DataContext抽象出来,那么在两个上下文中使用的基础LINQ查询是相同的?请查看http://compiledexperience.com/Blog/post/Domain-Driven-Design-Repositories-in-LINQ-to-SQL.aspx,以了解我所说的内容的示例! - Duncan
谢谢,这就是我想知道的。虽然大多数情况下都没问题,但如果真的出了问题,我不能冒险推荐这种方法。 - Duncan

6
令人沮丧的是,所有的>实现本质上都是漏洞百出的抽象,不能安全地假设在任何其他提供程序下仍然适用于LINQ-to-Objects中的工作。除了显而易见的函数映射外,像以下这些东西:
  • LINQ-to-SQL不可能支持所有函数/重载-在此处列出数据类型和函数(LINQ to SQL)
  • 此外,它取决于实际的数据库服务器; Skip/Take等在SQL Server 2000和2005+上的工作方式不同,并且并非所有这样的转换都适用于SQL Server 2000
  • EF不支持Single或Expression.Invoke(子表达式调用)或UDF使用
  • Astoria支持Single/First的不同用法;我记得它支持Where(pred).Single()-但不支持Single(pred)(这是LINQ-to-SQL的首选用法

因此,您无法真正使用IEnumerable来模拟数据库的单元测试,即使通过AsQueryable() - 它根本不够强大。出于这个原因,我个人将IQueryable和Expression远离存储库接口-请参见实用的LINQ


哇,我不是唯一一个尝试将IEnumerable转换为AsQueryable的人,而且我有一种预感这太美好了,不可能实现。但是我最近购买了Charlie Calvert的Essential LINQ - 他在附录中提供了这个链接来模拟 - http://andrewtokeley.net/archive/2008/07/06/mocking-linq-to-sql-datacontext.aspx我觉得另一种方法(上面概述的方法)给了我们更多的权力。嗯,我想我要回到完全分离的Mock和L2S Repos的道路上,这样至少我可以交换我的DAL。 - Duncan
顺便说一下,我在你的博客文章上发表了评论。很有趣的东西。 - Duncan

5
查询语法相同。如果使用 Enumerable.ToQuerable,类型甚至也相同。但是还有一些区别:
  • 某些查询仅适用于 L2O,并且在 L2S 中会导致运行时错误(例如,如果表达式树包含无法转换为 SQL 的函数。这不能在编译时检测到)
  • 某些查询在 L2S 和 L2O 上返回不同的结果(例如:Max([empty sequence]) 在 L2O 中将抛出异常,但在 L2S 中返回 null)

因此,最终你必须针对数据库进行测试以确保正确性,但我认为 L2O 对于简单、快速的单元测试非常好用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接