If we abstract out the DataContext, then are L2S and L2O queries identical?
I already have a working prototype which demonstrates this, but it is very simple and wonder if it will hold up to more advanced querying.
Does anyone know?
If we abstract out the DataContext, then are L2S and L2O queries identical?
I already have a working prototype which demonstrates this, but it is very simple and wonder if it will hold up to more advanced querying.
Does anyone know?
No they're not the same.
LINQ to Objects queries operate on IEnumerable<T>
collections. The query iterates through the collection and executes a sequence of methods (for example, Contains
, Where
etc) against the items in the collection.
LINQ to SQL queries operate on IQueryable<T>
collections. The query is converted into an expression tree by the compiler and that expression tree is then translated into SQL and passed to the database.
It's quite commonplace for LINQ to SQL to complain that a method can't be translated into SQL, even though that method works perfectly in a LINQ to Objects query. (In other cases, you may not see an exception, but the query results might be subtly different between LINQ to Objects and LINQ to SQL.)
For example, LINQ to SQL will choke on this simple query, whereas LINQ to Objects will be fine:
var query = from n in names
orderby n.LastName.TrimStart(',', ' ').ToUpper(),
n.FirstName.TrimStart(',', ' ').ToUpper()
select new { n.FirstName, n.LastName };
(It's often possible to workaround these limitations, but the fact that you can't guarantee that any arbitrary LINQ to Objects query will work as a LINQ to SQL query tells me that they're not the same!)
The query syntax is the same. If you use Enumerable.ToQuerable, even the types are the same. But there are some differences:
So in the end, you will have to test against a database to be sure, but I think L2O is pretty good for simple, fast unit-tests.
Frustratingly, all IQueryably<T>
implementations are, essentially, leaky abstractions - and it is not safe to assume that something that works in LINQ-to-Objects will still work under any other provider. Apart from the obvious function mappings, things like:
Where(pred).Single()
- but not Single(pred)
(which is the preferred usage for LINQ-to-SQL)So you can't really use IEnumerable<T>
for your unit tests simulating a database, even via AsQueryable()
- it simply isn't robust. Personally, I keep IQueryable<T>
and Expression
away from the repository interface for this reason - see Pragmatic LINQ.