Linq to SQL和Linq to Objects查询相同吗?

时间:2009-06-27 09:41:57

标签: linq-to-sql linq-to-objects

如果我们抽象出DataContext,那么L2S和L2O查询是否相同?

我已经有一个工作原型来演示这个,但它非常简单,并且想知道它是否能够支持更高级的查询。

有人知道吗?

3 个答案:

答案 0 :(得分:9)

不,他们不一样。

LINQ to Objects查询在IEnumerable<T>个集合上运行。查询遍历集合并针对集合中的项执行一系列方法(例如,ContainsWhere等)。

LINQ to SQL查询在IQueryable<T>个集合上运行。编译器将查询转换为表达式树,然后将表达式树转换为SQL并传递给数据库。

LINQ to SQL很容易抱怨某个方法无法转换为SQL,即使该方法在LINQ to Objects查询中完美运行。 (在其他情况下,您可能看不到异常,但查询结果可能在LINQ to Objects和LINQ to SQL之间略有不同。)

例如,LINQ to SQL会阻塞这个简单的查询,而LINQ to Objects会很好:

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查询工作,这告诉我它们不一样!)

答案 1 :(得分:6)

令人沮丧的是,所有IQueryably<T>实现本质上都是漏洞抽象 - 并且假设在LINQ-to-Objects中工作的东西仍然可以在任何其他提供者下工作是不安全的。除了明显的函数映射之外,还有以下内容:

  • LINQ-to-SQL不可能支持所有函数/重载 - 这里列出Data Types and Functions (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)preferred usage for LINQ-to-SQL

因此,您无法真正使用IEnumerable<T>进行模拟数据库的单元测试,即使是通过AsQueryable() - 它也不是很健壮。就个人而言,出于这个原因,我将IQueryable<T>Expression远离存储库界面 - 请参阅Pragmatic LINQ

答案 2 :(得分:5)

查询语法是相同的。如果使用Enumerable.ToQuerable,即使类型也相同。但是存在一些差异:

  • 某些查询仅适用于L2O,并且会导致L2S中出现运行时错误(例如,如果表达式树包含无法转换为SQL的函数。这在编译时无法检测到)
  • 一些查询在L2S和L2O上返回不同的结果(例如:Max([empty sequence])将在L2O中抛出异常但在L2S中返回null)

所以最后,你必须对数据库进行测试才能确定,但​​我认为L2O非常适合简单快速的单元测试。