Creating a Data Access Layer with LINQ to SQL

Building a genuine data access layer on top of LINQ to SQL raises a question that is harder than it looks: where do you draw the line between business logic and the DAL, and where does the query actually get executed?

The core concern is what the data access layer should return. The argument I find convincing is that it should hand back arrays of entities, or IEnumerable(Of T), and specifically not IQueryable(Of T). Returning IQueryable gives you more rope to hang yourself with. The caller can redefine the query that ultimately goes to the database, the caller ends up executing the query because of deferred execution, and the distinction between the business layer and the DAL blurs until it is gone.

That is the practical problem with deferred execution at a layer boundary. If you return IQueryable(Of T) from the data access layer, nothing has run yet. The query executes later, when something in the business layer or the UI enumerates it, which means your data access layer is no longer the thing deciding what hits the database. Returning List(Of T), IEnumerable(Of T), or an array of entities draws a clear line: the DAL fetches, everything above it works with what it got.

I have experimented with returning all four, and each has advantages and caveats. My research so far leads me to prefer IEnumerable(Of T), partly for the reason above and partly because LINQ itself operates on IEnumerable(Of T). Design your application around it and you find plenty of places where a LINQ query turns out to be an elegant solution.

There is a broader point here about standards, and it is the one I keep coming back to. When developers have to make a judgment call like this during routine development, choosing takes time, and different developers make different choices. The same developer may choose differently from one day to the next. That leads to inconsistency, which costs everyone reading the code later, and in the worst case developers start rewriting each other's work just to match their own preference.

Agreeing on a standard before integrating LINQ into a project seems like a smart move, especially on a team.