Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Cannot call methods on DateTime", and other limitations

Does anyone know of a definitive list of LINQ to SQL query limitations that are not trapped at compile time, along with (where possible) workarounds for the limitations?

The list we have so far is:

  • Calling methods such as .Date on DateTime
    • no workaround found
  • string.IsNullOrEmpty
    • simple, just use == "" instead
  • .Last()
    • we used .OrderByDescending(x => x.WhateverProperty).First()
like image 543
Richard Ev Avatar asked Nov 27 '08 13:11

Richard Ev


3 Answers

Basically, that list is huge... it is everything outside of the relatively small set of things that are handled. Unfortunately, the Law Of Leaky Abstractions kicks in, and each provider has different answers...

LINQ-to-Objects will do anything (pretty much), since it is delegates; LINQ-to-SQL and Entity Framework have different sets of support.

In general, I've had a fair amount of success using the DateTime properties etc - but in reality, you're going to have to ensure that your query expressions are covered by unit tests, so that if you ever change providers (or the provider gets updated) you know it all still works.

I guess one view is to think in terms of TSQL; there is no BOTTOM n, but there is a TOP 1 (re the OrderByDescending); In terms of string.IsNullOrEmpty, you could be quite literal: foo.Bar == null || foo.Bar == ""; and with DateTime.Date you can probably do quite a bit with DATEPART / the various components.

Another option with LINQ-to-SQL is to encapsulate the logic in a UDF - so you could write a UDF that takes a datetime and returns a datetime, and expose that via the dbml onto the data-context. You can then use that in your queries:

where ctx.Date(foo.SomeDate) == DateTime.Today

This approach, however, doesn't necessarily make good use of indexes.


Update:

  • The supported method translations etc are here.
  • The supported query operations etc are here.

For the full gory details, you can look at System.Data.Linq.SqlClient.PostBindDotNetConverter+Visitor in reflector - in particular the Translate... methods; some string functions are handled separately. So not a huge selection - but this is an implementation detail.

like image 179
Marc Gravell Avatar answered Oct 06 '22 00:10

Marc Gravell


LINQ is the language. LINQ-to-SQL compiles your LINQ command down into a SQL query. Thus, it is limited by the normal limitations of the TSQL syntax, or rather the items that can easily be converted into it.

As others have said, the lists of what you cannot do would be enormous. It is a much smaller list of what you can do. A general rule of thumb is to try to determine how the function you want to use would be converted into TSQL. If you have much trouble figuring it out, then don't use that function (or at least test it first).

But there is an easy work around to use LINQ commands that are not in LINQ-to-SQL. Separate the pure LINQ portions of your code from the LINQ-to-SQL portions. In other words, do the LINQ-to-SQL to pull the data in (with any functions you need that are available in LINQ-to_SQL), with the command to put it into an object (ToEnumerable, ToList, or others similar). This executes the query and pulls the data local. Now it is available for the full LINQ syntax.

like image 30
Carlton Jenke Avatar answered Oct 06 '22 01:10

Carlton Jenke


I created a Connect issue for String.IsNullOrEmpty():

Feedback: I want to use string.IsNullOrEmpty in LINQ to SQL statements.

Feel free to add your voice or vote to it, or to create other Connect issues for the various other methods that don't work in Linq to SQL. The squeaky wheel gets the grease.

like image 38
Ryan Lundy Avatar answered Oct 06 '22 00:10

Ryan Lundy