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

Dun*_*can 6 linq-to-objects linq-to-sql

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

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

有人知道吗?

Luk*_*keH 9

不,他们不一样.

LINQ to Objects查询对IEnumerable<T>集合进行操作.查询遍历集合并针对集合中的项执行一系列方法(例如Contains,Where等).

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 };
Run Code Online (Sandbox Code Playgroud)

(通常可以解决这些限制,但事实上你不能保证任何LINQ to Objects查询都可以作为LINQ to SQL查询工作,这告诉我它们不一样!)


Mar*_*ell 6

IQueryably<T>令人沮丧的是,所有实现本质上都是漏洞抽象 - 并且假设在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<T>用于模拟数据库的单元测试,即使是通过AsQueryable()- 它根本不健壮.就个人而言,出于这个原因,我保持IQueryable<T>Expression远离存储库接口 - 请参阅Pragmatic LINQ.


Nik*_*iki 5

查询语法是相同的.如果使用Enumerable.ToQuerable,即使类型也相同.但是有一些不同之处:

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

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