ASP.MVC: Repository that reflects IQueryable but not Linq to SQL, DDD How To question

Assuming that your LINQ to SQL (L2S) classes are auto-generated and reflects your underlying database, the short answer is: Don’t expose IQueryable of any of your L2S classes – it would be a Leaky Abstraction.

The slightly longer answer:

The whole point of Repositories is to hide data access behind an abstraction so that you can replace or vary your data access code independently of your Domain Model. That is not going to be possible when you base the Repository interface on types defined within a specific implementation (your L2S-based Data Access Component (DAC)) – even if you could provide a new implementation of your Repository interface, you would need to reference your L2S DAC. That wouldn’t play particularly nice if you suddenly decided to switch to LINQ to Entities, or the Azure Table Storage Service.

Domain Objects should be defined in a technology-neutral way. This is best done as Plain Old C# Objects (POCO).

Furthermore, exposing IQueryable gives you the opportunity to perform projections. That may sound attractive, but is actually rather dangerous in a DDD context.

In DDD, we should design Domain Objects so that they encapsulate Domain Logic and ensure all invariants.

As an example, consider the concept of an Entity (not a LINQ to Entitities Entity, but a DDD Entity). Entities are almost always identified by a persistent ID, so one common invariant is that the ID must be defined. We could write a base Entity class like this:

public abstract class Entity
{
    private readonly int id;

    protected Entity(int id)
    {
        if(id <= 0)
        {
            throw new ArgumentOutOfRangeException();
        }
        this.id = id;
    }

    public int Id
    {
        get { return this.id; }
    }
}

Such a class nicely enforces its invariants (in this case that the ID must be a positive number). There may be a lot of other, more Domain-specific invariants implemented in particular classes, but many of these are very likely to be at odds with the concept of projection: You might be able to define a projection that omits certain properties (such as the ID), but it will crash at run-time because the default values for the types (such as 0 for int) is going to throw exceptions.

In other words, even if you need only certain properties of a Domain Object, it will only make sense to hydrate it in its entirety, because that is the only way you can satisfy its invariants.

In any case, if you frequently find that you need to select only certain parts of your Domain Objects, it may be because they violate the Single Responsibility Principle. It might be a better idea to spilt the Domain Class into two or more classes.

In conclusion, exposing IQueryable sounds like a very attractive strategy, but with the current implementation of L2S it will lead to Leaky Abstractions and Anemic Domain Models.

With the next version of the Entity Framework, we should get POCO support, so it may move us closer to that goal. However, as far as I’m concerned, the jury is still out on that account.


For a more thorough discussion of a very similar topic, see IQueryable is Tight Coupling.

Leave a Comment