Search code examples
entity-frameworkrepository-patternservice-layer

Should repositories supply all the data to the services?


What I mean by that is, say I have a method in my repository:

Public Function GetCustomerByState(ByVal State As String) As IQueryable(Of Customer)

Should the service be able to get additional data in the form of say this extension to say get the orders for the customer:

<Extension()> _
    Public Function Include(Of T)(ByVal Source As IQueryable(Of T), ByVal Path As String) As IQueryable(Of T)
        Dim ObjectQuery = CType(Source, ObjectQuery(Of T))
        If (ObjectQuery IsNot Nothing) Then
            Return ObjectQuery.Include(Path)
        End If
        Return Source

    End Function

This extension is most likely used with a generic repository.

Or should you have concrete implementations of the repositories per aggregate root that return to the service exactly what it needs and nothing more or less?

Then, should your repositories even return IQueryable?


Solution

  • I would offer only limited set of methods like:

    IQueryable<T> GetQuery();
    T GetByKey(K key);
    

    The reason is that repository is used to provide abstraction of data access to agregation roots but the business logic is responsible for defining what data should be retrieved. If you pass too much logic into repository you will divide the logic between service and repository. Moreover most of your data retrieval methods in service will do nothing - they will just call repository method.

    Martin Fowler says this clearly:

    A Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection. Client objects construct query specifications declaratively and submit them to Repository for satisfaction.

    In past years Repository and UnitOfWork patterns became very popular in .NET world. But nobody speaks about third pattern from this family - Specification. Specification is an abtracted query passed to repository to define what data should be returned. .NET world doesn't use this pattern explicitly because IMO Linq-To-Entities queries are specifications.