Favor query objects over repositories

So I’m over Repositories, and definitely over abstracting your data layer, but where does that leave us? I don’t think creating an abstraction over your ORM provides much value, nor do I think it is necessarily bad if you use your ORM directly in the UI tier. After all, it’s pretty hard to suggest that this:

public ActionResult Index()
	RavenQueryStatistics stats;
	var posts = RavenSession.Query<Post>()
		.Include(x => x.AuthorId)
		.Statistics(out stats)
		.OrderByDescending(post => post.PublishAt)
		.Paging(CurrentPage, DefaultPage, PageSize)

	return ListView(stats.TotalResults, posts);

Is not maintainable. You can pretty easily write tests for this code, just going straight against the actual underlying data source. But queries can get hairy, and I might have too much going on in my controller action at some point that would necessitate some level of refactoring.

In the land of repositories, we might solve this by adding another method on a Repository to accomplish this. However, we really have another concept going on here – the concept of a named query. Instead of bloating a data access god class, why not just create an isolated class that encapsulates our query?

Let’s create a query that is just the extracted method and class of the query above:

public class ListPostsQuery
    private readonly IDocumentSession session;

    public ListPostsQuery(IDocumentSession session)
        this.session = session;

    public List<Post> Execute(int currentPage, int defaultPage, int pageSize, out RavenQueryStatistics stats)
        return session.Query<Post>()
            .Include(x => x.AuthorId)
            .Statistics(out stats)
            .OrderByDescending(post => post.PublishAt)
            .Paging(currentPage, defaultPage, pageSize)

My query encapsulates not the data access, but the query itself. However crazy my query gets, it’s isolated from my controller action:

public ActionResult Index()
	var query = new ListPostsQuery(RavenSession);

	RavenQueryStatistics stats;

	var posts = query.Execute(CurrentPage, DefaultPage, PageSize, out stats);

	return ListView(stats.TotalResults, posts);

We could have used dependency injection to push our query object in, but I’m still not convinced an application as flat as RaccoonBlog needs a container. It’s just not that interesting, yet.

Instead of a bloated repository with queries as a method, each of which is only used in one location, I have a class that encapsulates the concept of a query. I didn’t bother trying to create some layer supertype for queries – I don’t think that has much value either.

But in the case we want to isolate queries, building a concept around that purpose serves a lot better than dumping everything into a common class.

About Jimmy Bogard

I'm a technical architect with Headspring in Austin, TX. I focus on DDD, distributed systems, and any other acronym-centric design/architecture/methodology. I created AutoMapper and am a co-author of the ASP.NET MVC in Action books.
This entry was posted in DomainDrivenDesign. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • I’m in favor of this approach. I used a similar approach a while ago. However the query was executed by another object which made it easier to insert stubs for testing.

  • Pezza

    I agree that I prefer the class-per-query method over the adding-methods-to-repository approach but… how would you extend your example if the same View also needed other supporting queries such as; a list of authors; some author statistics; list of search filter options etc… Would you try and batch these together and pass them in the ViewModel or ajax them in to the page as needed?

  • The tricky thing with both query objects and repositories is that it’s always hard, for me at least, to figure out when you should stop adding parameters to the query (like you now have done with paging, but there might be more along the line) and split it off into a new query object.

    • jbogard

      What about creating a single class that represents the query params then?

      • Yes sure, that makes sense. Moving paging parameters to a “QueryParameters” or “QueryPaging” class or whatever. It’s just that when you get subtly different behavior with certain parameters that it can get a bit hairy.

        It’s what I’m seeing in some of our repositories here, is that after a while you get a whole bunch of “GetBy…” methods, all subtly different. But that’s more a general code smell that’s not necessarily solved by query objects, I meant to say.

        In general though, although I also prefer the query object pattern, I think the most important part of your post is “preferring simplicity” and having as few abstractions as possible.

  • hazzik

    Why not include total results as a field of Query result?

  • hazzik

    I’m doing so about two years. I have IQuery{TResult, TCriteria} interface and three related classes: MyQueryResult, MyQueryCriteria and MyQueryQuery.

  • EisenbergEffect

    I couldn’t agree more.


    You can also use extension method that’ll help your for combining queries (eg : paging and filtering for instance). Anyway i totally agree with you on this point, it’s way more confortable, with repository you keep doing plumbing code instead of focusing on the business.

  • I hope there is a renaissance of posts and topics like this. Seems many in the community think these topcis are old hat and not worth discussion. The curve as a whole has not moved far enough yet for us to ignore them.

  • Khalid Abuhakmeh

    I like how RacoonBlog has a TaskExecutor which allows you to intercept a task in the case of a Unit test. The same thing would be helpful for a Query. So instead of what you have above you would have the following.

    var result = Queries.Execute(new ListPostsQuery { CurrentPage = 1, PageSize = 20 });

    Since all your queries run against RavenDB you can assume all queries need a document session and can inject the session into a property.

    With this approach you can unit test your query and the place that calls your query separately and have smaller unit tests.

  • kevdog

    Love this idea. I was watching a Pluralsight video this week with so many layers of abstraction I felt I was looking down from the Tower of Babel.

  • Instead of making separate object, I will probably try to get rid of infrastructure stuff. Statistics, Paging and ToList should probably go somewhere in helpers. In this case you will only have only query in your controller action that will look pretty readable and maintable.

  • This is all well and good, but if you follow this pattern on a controller with several actions you’re just trading a bloated repository with a bloated controller ctor and a wall of private fields (if using DI).

    I’m not suggesting there is a whole lot of value in a repository abstraction, but I don’t really see how a bunch of query classes is fundamentally different than a bunch of query methods in a repository class. There’s some value in the repository in terms of ease of development – when you start reusing some queries and/or have a lot of them used by the same controller it’s a lot simpler to inject a repository and call methods on it than constantly adding fields and changing the ctor parameters every time another query is used.

    • jbogard

      I would expect to have at most 1 query object per action, so it shouldn’t really get too bloated. And even then, only when actually needed.

      For me, having all queries in one class is just a lot to conceptually manage, imo. You have to wade through the stuff you don’t care about to find the thing you do.

      • RyanVice

        If it’s one query per action then queries don’t represent cross cutting concerns and you might want to consider injecting an abstract query factory instead so that you can lazy instantiate your query objects. But as always it depends on the situation so just another thing to consider in your design.

      • Michael

        Why not using those query objects inside repository? This way repository is just an aggregate for preventing constructor overinjection (we injecting query objects in controller right?)

        • inmytime

          +1 on that. This is exactly how I approach it. This seems to be how big composite patterns came to be like MVC. Much ado about models, stateful/data objects (or PODs if ur old skewl) and views, but no controller. Then, viola, a controller came to the rescue and all was well. Yet, interestingly, the variations still exist (MVP, MVVM, etc.). I see two possible views of a repository: business context (i.e. a controller) or a service. Lately, I’ve toyed with the idea of a more service-like approach, regardless if I ever actually hosted it as a service. I guess we spoiled humans like flavors…choice.

          • inmytime

            Correction, a business view, not a context or controller. Inherently, as an aggregate root, it abstracts AND encapsulates the fine grain into a more coarse grain, a view. This is my take on it, anyway.

    • magellings

      You can avoid DI by just testing straight against the underlying data source. You can swap in SQLite for faster tests.

  • I do like this approach but what about when your domain model is reused across multiple apps (web app, web api, background workers). In this scenario you can’t just implement everything in the web app because you lose the ability to reuse logic across the entire solution. I suppose in that case you would still dump the repository and instead put the data access directory in the “Business Logic” layer?

    • A lot of people, myself included, find that these queries rarely are re-used. And planning for situations to facilitate is wasted time that brings it’s own problems.

      Dump it in the controller. When the problem manifests then look at your context-specific factors.

  • Philip Patterson

    In the example you provide I tend to agree that it’s not going to buy you a whole lot to have every interaction with the data store abstracted through one off methods on one repository. I’m not 100% sure how this extends when the calling code needs to handle error/exception conditions.

    In your example I suppose you could argue (and I would probably agree) that this is the responsibility of the ListPostQuery class and you can mock the IDocumentSession for testing purposes.

    I’m not sure that this is all that different at that point from the repository pattern as IDocumentSession has a Query method taking a generic parameter of type T.

    I may need to spike out a solution to investigate this some. I like the idea of the small query classes as I think it improves readability and it is in line with the idea of small components. I definitely consider it an improvement over a generic IBlogRepository interface with methods for every class in the domain. Of course you could implement several different interfaces as opposed to the one, but RavenDB already has an abstraction that does the same thing, so at that point why create custom repositories?

    You’ve definitely given me some food for thought.

  • Ayende Rahien

    In this scenario, if I have a class, then all the parameters to the execute for paging, stats, etc would be properties, instead.
    Much nicer to work with in general.

    • Definatly easier. Also just define a layered supertype with all the paging and sorting information.

  • Simon Skov Boisen

    I like this approach and it reminds me a bit of the specification pattern where you encapsulate business logic in objects which can then be combined to form chains of business rules. I wonder if you couldn’t do something similar with your query-objects which would allow one to encapsulate reoccurring queries and reuse them in other contexts.

  • This approach is good when you are building a data-centric application without much business logic. Once you have more complex business logic, using a repository is (one of) the way(s). As some people already mentioned, it is very hard to reuse logic. Furthermore, testability suffers immediately. Repositories are much easier to test, while this query-like approach is very rigid.

    • jbogard

      I haven’t found that problem with testability. But my tests might look different than yours.

      Can you elaborate a bit more about reusing logic amongst queries? Can’t two queries share common logic just like a single class would?

  • Pingback: The Morning Brew - Chris Alcock » The Morning Brew #1206()

  • Blake Blackshear

    I have found this to be a leaky abstraction because it needs to be aware of how it is used in the view to avoid N+1 issues. The only answer seems to be to avoid reuse and then it is really just a way to keep ISession out of the controller for testability. As far as testability is concerned, I tend to like this pattern more than repositories.

  • I have been doing this exact approach for the last year. Easier to maintain and you don’t end up with a bunch of methods on your repositories that are really only ever used for 1 screen.

  • I do something similar, but rather than instances of classes, I use extension methods that operate on IDocumentSession. That gets the same encapsulation effect without having to create an instance of a class. For example, I could define your lists posts query as such:

    public static IQueryable<Post> ListPosts(this IDocumentSession session, int currentPage, int defaultPage, int pageSize, out RavenQueryStatistics stats){ … same implementation body…}

    And then call it like this:

    var posts = session.ListPosts(CurrentPage, DefaultPage, PageSize, out stats);

    The encapsulation effect remains, but you don’t have to instantiate anything.

  • That pattern is better than Repository, but still I don’t think that it gives you value if you use it everywhere. It just adds another level of abstraction over the logic and that is one of the reasons we leave Repository pattern in the first place.

    The only place it could give you value is if you need to re-use queries. But as we know that is VERY rare in real applications. All in all – reusing queries should be a business decision(depending on the current use case), not a technical one.

  • I Think this is a pretty nice approach and you can easily test each of Query classes. Would you prefer integration tests for each query class? I was also thinking that injecting a IXXXQuery class into the controller you can provide a stub when testing the controller and then assert on the action methods of the controller.

    Although I am not using this technique, I think it is quite nice, We are injecting IXXXReadService Oriented classes and we use the ISessionFactory directly to project Dto straight into the view models and bind. Also we use IXXXWriteService’s to update the model which we use the repository to rehydrate the entity i.e Customer etc. I find this approach works very well as the repositories tend to mainly have methods like GetById(), GetByName(), GetByCode etc and Save(). Sometimes there are a few methods like GetCustomersThatHaveOutstandingOrders() in a repository being used by a WriteService and we then perform business operations on the entities the commit the transaction after.

    How do you find that IReadServices compare to smaller focused QueryObjects? Is it just more beneficial as you have less methods on the class making it more focused and adhering SRP?

    I actually dont mind repositories to be honest. I think the real issue with them is more with people loading fully loaded objects and then projecting them to views causing a lot of SELECT N + 1 issues and requiring things like auto mapper whilst being far easier to have a QueryObject / ReadService that is just focused, and optimised for the query which is being used for the specific view.

    Keen to get you thoughts and opinions.

    Blair Davidson.

  • Daniel Marbach
  • Oliver

    This is what I’ve been using for some time :
    public abstract class Query{ public IDataSession Session { get; set; } public ICache Cache { get; set; } public abstract void Execute();}

    public abstract class Query : Query
    public T Result { get; protected set; }

    public abstract class Command : Command{ public T Result { get; protected set; }}

    public abstract class Command{ public IDataSession Session { get; set; } public ICache Cache { get; set; } public abstract void Execute(); protected void ExecuteCommand(Command cmd) { cmd.Session = Session; cmd.Cache = Cache; cmd.Execute(); }
    protected T ExecuteCommand(Command cmd) { ExecuteCommand((Command)cmd); return cmd.Result; }}

    usage :

    public class GetBooksByAuthor : Query<IEnumerable> { public int AuthorID { get;set; }
    public override void Execute() { Result = …. // get books from db or cache } }

    public void Foo()
    var booksByAuthor15 = Query(new GetActioneeInfo { AuthorID = 15});

    ExecuteCommand(new DeleteBook { BookID = 24});

  • Oliver

    dang…sorry for the bad formatting

  • Jimmy, this does sound convincing so in NHibernate land we can use the same techniques, unit test controllers against the DEV database and when things get scary create a `object query`.

    One question, in a bigger system (e.g 25ish tables) are you finding that you are creating lots of query objects as you have tons of paging to do?

    I am wrestling this in my mind as I am about to embark on a green field project using NHibernate.

  • kamranayub

    Cool approach. I tend to use a repository layer and an app service layer for business logic and that seems to work pretty well for me. I test against the service layer and above for all my integration tests, since my controllers are pretty dumb.

    This is also useful because I typically have MVC controllers and Web API controllers and scheduled jobs that need to use the same business logic, and since it’s all in the services, I can easily call them and reduce duplicate code.

    Since the service layer is “workflow” oriented, I don’t need to create methods on the repositories that are used once, since those go in the service layer. When I find I call the same repository with the same query, it becomes a method then, so it stays dry.

    The thing I like about your approach is I could easily swap out my repos with this object query pattern.

    • Rick

      I use Service/BL layers as well but the way I see it just inject the context into the service layer and be done with it. The service is meant to do a handful of business logic and often that business logic is done via linq done on the context. I don’t see a big need to add repositories on top of that or abstract out each query that the service needs to it’s own class. Seems way too much bloat for not much gain.

      Grouping things by services just cuts down on clutter and makes things much easier in my mind. Then just inject this into the controller. Not to mention you can make different implementations now since it has an interface to make it extendable.

      interface IOrderingService
      List GetOrder(int id);
      Order CreateOrder(int id, int qty, int customerId);

      class OrderingService : IOrderingService
      private OrderContext context;

      public OrderingService(OrderContext _context)
      context = _context;

      public List GetOrder(int id) { return context.Orders.Find(id).ToList() }

      public Order CreateOrder(int id, int qty, int customerId)
      // create the order object and add to the context.Orders table and return the order object

  • Pingback: Build Reusable, Testable Queries Part 1 « Alexandre Brisebois()

  • Adam

    This is approach that I like the most. I have a lot of problem to convince people that ORM provide layer of database access and we don’t have to use Repository over ORM.

  • KevinLaBranche


    Great post. I just finished a small asp.net mvc app and used a repo to make it unit testable. I’m getting ready to start another small mvc app and have been reading this and several other posts along these lines.

    Am I correct in that you are suggesting replacing the unit test for an integration test for the controller actions using an ORM/query object (“You can pretty easily write tests for this code, just going straight against the actual underlying data source.”)?

    In my case, this would mean that most of my tests become integration tests instead. Perhaps my usage/understanding are lacking in this area (and they are) and/or it’s the reality of having a simple domain for this application and being heavily CRUD based.
    Overall, great food for thought, as usual.

    • Reddy I. Bell

      This is just an example, you are not meant to copy an past the tutorial. In YOUR application, you could inject the command into the controller so that in your test project, you would inject a stub deriving from the query command and not hitting the database.

  • Ryan Vice

    Definitely prefer Query Object to Repository pattern. Query Object can take more code to create a simple CRUD operation than a good generic Repository Pattern implementation but Query Object really goes a long way for code organization and preventing controller bloat. We provide both on my current project so that developers can choose which approach they prefer and use our generic Repository to quickly grab low hanging fruit and then put the extra effort into building a Query object when they are dealing with more complex queries and want to get closer to the metal with the ORM.

    That said, to me most Repository pattern implementations I’ve seen are closer to a Transaction Script and in that context I’d probably always prefer Query Object and not even bother providing a Repository pattern alternative. Transaction scripts just end up being a big, confusing, bloated interface on any decent complex project.

  • Pingback: Testing with queries and repositories (a simple example) | Jimmy Bogard's Blog()

  • Edward

    Jimmy, I don’t really agree with you though. In my opinion, I think your style is tightly couplings Raven to your controllers. The question I have for you is, what’s the level of effort in case you decided to use EF instead of Raven.

    • jbogard

      If there was an actual business need to be able to switch out underlying data providers, I would architect things differently.

      Putting it a different way, I don’t fabricate business needs, I work with the business to prove that needs exist. I don’t like speculative architecture.

      Remember, we’re trying to match our code to the constraints we’re working under. I don’t have a constraint to have to be able to switch ORMs or database technologies.

      However, if that need actually existed, I would provide seams for doing so, and isolate as I see appropriately. So for the context you described, I wholeheartedly agree with you!

      • Reddy I. Bell

        Seriously, I love reading you, I’m so in line with what you’re saying.

  • Morten Jacobsen

    I really like this approach, since I too find it hard conceptually to wade through a large repository containing lots of query methods..

    My question would be this: You mention that you would generally restrict controllers to one query object per controller. Does that mean that your controller would project your domain classes to some kind of DTO that contains the data or do you prefer to return the entities directly?

    What if you need to fetch multiple types of data, like blog posts and maybe a list of all blog tags? Would you then have separate controllers for each of these queries with one query object per controller or would you have one controller with a query object that fetches both lists?

    • RyanVice


      I know your question was for Jimmy but the way that we have tackled this on my projects is by using a View Model (UX) or RequestResponse (Web Service) approach which means that each action would return a DTO (View Model or Response). Then you have your query object encapsulate all the querying logic needed to get the data needed by the DTO that is returned from your action method. We actually use stored procedures for this a lot of the time as it’s easier write complex queries for most developers in a SP than using an ORM API. This allows you to maintain a thin controller but still have good code organization. To make things easier use Auto-Mapper to implement the Entity Translation pattern in the Query Object to move data out of your entities an into the DTO.

  • Matteo

    Is it just me or there is code missing between “to suggest that this” and “Is not maintainable”?
    It’s not the first post I find with missing code or paragraphs.

    • jbogard

      There is something missing there, I’ll get that fixed.

  • While I don’t agree the repository pattern doesn’t provide value even in simple cases, you can easily use either query objects of specification patterns with your repository to get the same benefits you have here, and vastly reduce the amount of non-generic code you have to write.

    Simply have your IRepository base interface have a method of GetBySpecification (or if you want, GetByQueryObject). Pass in a Specification – you now have an extensible query capability without littering repository code all over controllers and other objects. In addition like your query objects you have reusable components to create more complex queries.

  • Alexey Zimarev

    I do IQueriable extension methods (basically this is Ayende’s idea), with NHibernate. This way I can define my queries separately from the actual paging and fetching so I can defer ToList and also add some more conditions/projections to the same query if I need.

  • inmytime

    Thank you for your posts and the insights that you labor over and give up so freely.

    In short, my view is to employ both “domain” repositories and query objects (even a query model, why not, noting relationships and dependencies of queries), once the system has enough complexity – business rules, policies, workflow, etc. – to warrant it. Don’t bloat the poor repo with mundane expressions, don’t hide business logic in the queries, but neither rob yourself of binary reuse and maintainability by ignoring good component factoring.

    Now for the long…

    There seems to be a syndrome of the “God coder” that exacerbates this issue. One should code for the masses, and make it easier for the next guy. That is the acid test of the principles, which are wisdoms, and patterns, which are appropriate applications of those wisdoms. Enter composability. By the time I get to the application layer, 3 or 4 lines of code ought to make a truck load of things happen…safely and reliably. I digress.

    Let me test how far off base I am. Isn’t the purpose of repositories to represent aggregate roots? And in a domain sense, that means being in charge of coordinating a “neighborhood” of the domain, probably participating in a transaction. Moreover, in DDD culture, let’s not forget all the business logic! ORMs, DAOs, ActiveRecord, DataGateway, and to an extent, CQS/CQRS all address data and transport things, not so directly the business. So I too strongly dislike the mass of data-centric repository implementations out there; they are missing the business (pun intended). However, as real business objects, they do. Indeed, they tend to be meatier, but done right, should be reflective of the domain. It is a contract. I help enforce this contract by with an IAggregateRoot interface. Each domain object gets marked that ought to be a root. If some junior later decides to try to make a repo for an OrderDetail…*bonk*, no sir, no compile. It had better be a VERY deliberate, purposeful decision with the business to back it up.

    Another thing I have explored lately is treating the repositories more like “Entity-centric services” (contemporary service-orientation lingo). That forces me to consider carefully what they yield and their parameters, again noting that they should “help” with a good amount of business logic – not merely mundane data access. So they are more coarse grained, ideally stateless and also take a contractual form, plus offering inter-system – or even inter-domain (B2B) – potential.
    Regardless, “repositories” ought not ever again be thought of as “data access” strategies! I really think it’s all in the name. It is the psychology of the term, the wrong taxonomy for what its real intent.
    I have a LOT more thinking to do on this topic, and some of you out there are a lot further along.

  • adrianoconnor

    I don’t understand why we hardly ever see the ActiveRecord pattern in .NET apps. It’s such a natural way of working, that (in my eyes at least) any other abstraction feels clumsy by comparison (and Repositories feel comically quaint at best). This post feels to me like it’s heading away from Repos, towards ActiveRecord, but kind of stops half way.

    Castle Project has a very decent ActiveRecord library, though it’s not hard to write your own generic base class for this pattern — all you need to implement are simple Find(), Update(), Delete() methods, and you can also add base-layer methods for initializing Linq queries that sub-classes can pick up and turn in to nice helpful (and easily testable) Member methods (e.g., Person.FindAllByNamePaged(…) or whatever.

    I don’t know, maybe I’m missing the point of this post, but a lot of stuff happens in .NET today that I don’t really see the point of. It’s as if we’re trying to be more Java like than Java.

    • jbogard

      Check out Simple.Data, it’s probably more what you’re after.

      Just as an aside, on a new project I’m starting on, we’re just going PetaPoco. The site has less than 10 controllers, so there’s not much need in building patterns like this.

      • adrianoconnor

        Thanks for the pointer; I hadn’t heard of Simple.Data, but it looks really great. Very interesting looking through the code. I’ll definitely give that a go.

  • Pingback: Onion Architecture Softio Blog()

  • Pingback: Links of interest #Week2 | Louis Turmel Blogs()

  • Pingback: Links for May 18, 2014 | James Holcomb()

  • tuespetre

    When you say “My query encapsulates not the data access, but the query itself.”, I have to do a double take. The moment you slap an interface on to that thing, you are able to substitute a different implementation that uses a different data technology. Your controller would never have to reference a specific data access technology. I would say it very much so encapsulates the data access.

    • jbogard

      I guess I meant that it encapsulates the interaction at one level up from merely abstracting the ORM via a repository.

      • tuespetre

        I see. I’ve taken the pattern from this post to heart; it conforms to SOLID in every way I can think of (while providing a nice overview of application functionality in solution explorer!)

        Thank you for your response and for everything you’ve shared.

  • Honestly I still have a hard time grasping exactly how CQRS is meant to work and the benefits. I’d love to see a full blown series or video somewhere explaining the basics and some solid examples and use cases. I like what I’m reading about it versus the traditional either using a Repository or just hitting a DbContext or the like directly from an ActionResult method in a controller, but how to actually implement CQRS in an application gets confusing.

    • jbogard

      Did you see my controllers on a diet series of posts back in October?

  • Pingback: Is the Repository pattern useful with Entity Framework? | The Reformed Programmer()

  • Pingback: james mckay dot net » Query Objects: a better approach than your BLL/repository()

  • Pingback: Repositories On Top UnitOfWork Are Not a Good Idea — Rob Conery()

  • Shayne van Asperen

    I took a slightly different approach with the query object pattern library I wrote for NHibernate: https://github.com/shaynevanasperen/NHibernate.Sessions.Operations

    It makes
    it easy to build and consume your own query objects, with support for “3rd level” caching and
    query-result transformation. It provides an IDatabases interface, which you use to invoke queries
    and commands. If you derive your query and command objects from the provided base classes, you
    can then mock calls to the IDatabases interface in your unit tests.

  • This is completely inline with the frustrations I’ve had in the past over larger Data-layer god classes. Have you seen the work being done for Highway Data framework? https://github.com/HighwayFramework/Highway.Data

    • jbogard

      Yeah I think I’ve seen a few presentations by Devlin and friends.

      One interesting difference is we’ve more or less eschewed any in-memory repositories/DbContexts. We always have to write the integration test that hits the real deal, going through all the SQL generation and whatnot. It’s always cool to see different people come up with the same end results but with slightly different implementations!

  • Rick

    Breaking out each query into it’s own class just seems like insane bloat. I do agree with not using the repository pattern (especially if using EF or some other ORM already). I much prefer to think of applications as 1 or more “services”. Each “service” has the db context and each service has functions that do things that service should do. All the business logic for that logical service are in that service class. DI the context into the service class and DI the service into the controller. Now this service can be it’s own DLL project so all that business logic can be reused many different ways to Sunday later if needed.

    • jbogard

      What’s bloated exactly? It’s just the logical conclusion of SOLID. A service has many responsibilities, a query object has one. A service has many interface methods, a query method has one. It really doesn’t get more SOLID than that. In practice, in applications with hundreds of queries/commands, we never saw the “bloat” issue. We only saw small, very tightly cohesive classes that serviced one and only one top-level UI request. It’s actually quite liberating, as each new feature to the application does not need to invent new services or service methods, it’s merely adding new handlers for very specific business needs. So far, our devs have enjoyed the move from service/repository to query/command-land, not looking back.

      • Rick

        The bloat, by the basic definition, is that you have 11 lines of boiler-plate code per query and 1 cs file per query (or a few with a bunch of classes in it which isn’t much better) cluttering up your solution. That’s the bloat that I meant specifically. The only bug free code is code that you never write so keeping things slim in most all aspects is ideal in my mind.

        Don’t get me wrong I’m done with repositories as well and just use the ORM directly in my service, but a class per query just seems a little overkill.

        “and I might have too much going on in my controller action at some point that would necessitate some level of refactoring.”

        The fact that you say “I might have too much going on in my controller action” tells me that your controllers may be bloated to. Take all that stuff and put it in the service. Controllers, in my view, should simply call a service function or 2 and only act as the middle man between business logic (service) and view (or api result). I get your design if you’re doing other stuff in the controller and you want to break the controller out some more, but I’d say break it all out into a service class and be done with it.

        Maybe you often see service classes that are not broken out enough and just contains everything. The logical breakout of a service class is for sure and art form that takes time to get the right balance.

        These are all my opinions on the topic and I’m always interested in hearing others, which is why I read this, and I find going back and forth is a good way to find this out. I in no way mean disrespect but I often write things that come off as challenging but it’s how I best learn. Just wanted to give that disclaimer to avoid any possible misreading of what I wrote :)

        • jbogard

          It’s hard to talk about this without code, but here’s an example of a typical application we write these days with this sort of architecture. A controller:
          A complicated query:
          A complicated create/edit page (command + query):
          I’m not really concerned about adding of files – that doesn’t really add to the conceptual bloat, especially since each file represents a particular responsibility with a particular request. There’s no code really added or removed, originally this was all in the controller (or defactored from services and repositories), and I just refactored the business logic in to smaller and smaller cohesive pieces. I’m trading a uniform interface (all things go through queries and commands) with more classes. However, the classes aren’t abstractions or layers, which is where I typically see applications with large numbers of classes come from.

          • Rick

            From what I can see you’ve basically just created a micro service. Pretty much what you have there is what my services look like but you add this abstraction on top which I don’t do. The only difference is my service will have a couple more things that hit the context. I don’t see a huge difference myself. Maybe the services you’ve seen people make have been nastier? Possibly because the logical breakout of a service is left to interpretation by the coder vs this hard and fast rule?

          • jbogard

            Probably so, I wouldn’t doubt the method body of the service you describe is the exact same of the method body of one of my handlers. Otherwise, you delegate to a service in a controller, I delegate to a handler (but through a mediator so that I don’t have to have a handler dependency per controller action).

            How do you design the scope your services? Do you make it one per controller, per entity, per feature…?

          • Awesome, looking at your code made this click for me. Thanks for the example code.

  • Darren Sherwood

    For those who are thinking a Query object per query is overkill, you could well be right depending on your circumstances, something you could do is have a ‘FooQueries’ object, this would essentially be a like a Repository, but only for Queries. ‘Foo’ could of course be your ‘domain aggregate’ in the DDD sense. You would stick to a single command object per command to enable simple transactions, avoiding the need for the complexity of the Unit Of Work pattern.