Avoiding the Repository Pattern with an ORM

For many years now I’ve advocated not using the repository pattern on top of an ORM such as Entity Framework. There are many reasons why that I’ll try and cover throughout this post based on ways that I’ve seen it implemented. Meaning, this post is talking about poorly implemented approaches or pitfalls that I’ve seen.

To clarify, since this topic seems to really fire people up, I’m not saying that you shouldn’t use the repository pattern. I’m going to clarify why I don’t think under certain situations it’s very useful and other situations that I do find it useful.

This post was spurred on by a blog post and tweet:

IQueryable

The first thing I’ve seen with a repository is exposing IQueryable<T> (or DbSet<T>) from the underlying DbContext in your repository. This serves no purpose. It’s not abstracting anything at all.

What’s even worst is the consumers/callers don’t necessarily know at what point will they actually be retrieving data (doing I/O), unless you’re aware that the underlying IQueryable is coming from Entity Framework., Now when you call a method that materializes your query and actually hits the database (such as ToListAsync()).

Lazy Loading

Second, to this point is now if you have any type of navigation properties and are accessing IQueryable<T> from repository consumers, you must either eager load (via Include()) or have your consumers do the Include() or not realize all navigation properties are lazy loading.

Again, consumers are now aware of the underlying implementation that is Entity Framework.

IEnumerable

To overcome these issues, usually what comes next is avoiding the IQueryable<T> by returning an IEnumerable<T>.

The issue now is since you’re taking away control from the consumer, you must decide what data to Include() and Select() behind query methods.

What this often turns into is a pile of methods with various filtering parameters that could have been much easier expressed via a LINQ expression against the DbSet directly.

Query Objects

So if I don’t generally use the repository pattern, what do I use? Query Objects.

For querying, I’d rather have specialized objects that can return very specific data for the given use case. When implementing in vertical feature slices, as opposed to layers, each query is responsible for how it retrieves data.

The simplest solution is to use the DbContext and query directly.

The primary benefit is query objects only have dependencies that they actually require. Because each query object defines its own dependencies, you can change those dependencies without affecting other query objects.

A simple example of this is if you wanted to migrate from Entity Framework 6 to Entity Framework Core. You could migrate one query object at a time to EF Core instead of having to change over an entire repository that is highly coupled.

Testing

I can see the argument for using a repository because testing was difficult with EF6. However, with EF Core using the SQLite or the InMemory Provider, testing is incredibly easy.

I’ve written a post on how to use the SQLite provider with an in-memory database.

Testing a Query Object becomes incredibly easy without the need to mock.

Caching

Another argument for using the repository pattern is being able to swap out the implementation for a “cached repository”. I do use this pattern but in very select cases. Most times this is across bounded context were cached or stale data is acceptable.

If you decide to swap out the implementation of your repository, which was previously always hitting the database (point of truth) and now is using a cache implementation, how does that affect the callers? How quickly is the data invalidated?

Data can be stale the moment you retrieve it from the database, however adding caching to your repository without your callers knowing it can have a big impact on behavior.

Aggregate Root

One place I do often use a repository is when accessing an aggregate (in DDD Terms). My repositories often only contain two methods, Get(id) and Save(aggregateRoot).

The reason I do use a repository in this situation is that my repository usually returns an object that encapsulates my EF data model. I want it to fetch the entire object model and construct the aggregate root. The aggregate root does not expose data but only behavior (methods) to change state.

Repository Pattern Related

Enjoy this post? Subscribe!

Subscribe to our weekly Newsletter and stay tuned.

Event Sourcing: Projections with Liquid Projections

Liquid Projections

Projections are an important yet pretty simple concept when working with event-centric or event sourcing systems. The concept is to build a state from a stream of events. In my previous post, Event Sourcing with SQL Stream Store, I made a pretty basic projection to keep the current account balance. In this post, I’ll use Liquid Projections to accomplish the same task.

I recommend checking out my post on SQL Stream Store as I’m using the same example/demo application in this post.

Liquid Projections

Liquid Projection is a library for building projections. The concept and API are pretty simple, and I’ll cover the basics in this post.

First I’ll update my Demo Application to use the Liquid Projections NuGet package.

Event Map

The first building block is creating an event map. The idea is to map an event to an action that we want to be invoked when the event occurs. We can use the EventMapBuild<TContext> to create all of our event mappings. The TContext can be anything but I’ll be using it to mutate the state that represents the current balance.

As a refresher from my previous post, here is the Balance

Now using the EventMapBuilder<Balance> to handle the Deposited and Withdrawn events.

You’ll notice call Build() on the EventMapBuilder<Balance> which will return us the EventMap<Balance>. At this point, you can call Handle() to pass in the events incoming from our subscription with our current Balance.

Conditions

There are also some nice additions such as providing conditions for when to execute a map. For example, if you wanted to handle only deposited events where the amount was greater than 100.

Inheritance

There is also support for inheritance, which means since my Deposited and Withdrawn events inherit from the AccountEvent base class, I could also have done

Event Store Integration

The next on my list is write this up directly with to something like Event Store or SQL Stream Store. Stay tuned.

Check out Liquid Projections on GitHub for more.

All the source code shown in this post is available on GitHub.

If you’d like a more detailed contented related to various aspects of event sourcing, let me know in the comments or on twitter.

Related Links:

Enjoy this post? Subscribe!

Subscribe to our weekly Newsletter and stay tuned.

Is CQRS Complicated?

There are many misconceptions about CQRS. It’s often referenced alongside other patterns that can make it seem difficult and complicated. Is CQRS complicated? No. CQRS is simple. Really simple.

What is CQRS?

First, let’s tackle at the very core what CQRS actually is.

CQRS stands for Command Query Responsibility Segregation and was coined by Greg Young. CQRS is related to CQS (Command Query Separation) principle by Bertrand Myer which states:

Every method should either be a command that performs an action, or a query that returns data to the caller, but not both.

In other words, a command is a method that mutates state and query is a method that returns state. A method generally doesn’t do both, but there are exceptions to this rule.

CQRS takes CQS a step further by separating commands and queries into different objects.

To use an exampling in C#, here is a shipment class has two methods. It applies CQS, in that each method either performs an action or returns data.

CQRS Applied

If we take the above class and were to apply CQRS, we simply just need to turn this into two objects. One object would be used for mutating state (ShipmentCommand) and the other object for returning state (ShipmentQuery).

That’s it. You’ve just applied CQRS. Wasn’t that totally unexciting?

Misconceptions

I suspect the reason for the misconceptions about being complex and difficult stems from people seeing a diagram like this:

Is CQRS Complicated?

If you search google images for CQRS, you are bound to find almost every diagram that looks like the one above or some variation of it.

Is the diagram applying CQRS? Yes.
Is the diagram only applying CQRS? No.

When you hear talks or read about CQRS you are often also hearing about a bunch of other patterns or technology. Mainly those that in attempted to be represented in the diagram above.

You do not need:

  • Message Broker or Bus
  • Messaging
  • Domain Model
  • Domain Events
  • Event Sourcing
  • Eventual Consistency
  • Separate Models for Reads and Writes
  • Domain Driven Design

Enabler

I often say that CQRS is an enabler. It enables or facilitates using other patterns that often fit well together. This is why you often see CQRS and Event Sourcing applied together.

CQRS is not Event Sourcing nor does it require you to use Event Sourcing. CQRS simply fits well and enables you to apply Event Sourcing.

Fat Controller CQRS Diet

I’ve blogged a bit about how to implement CQRS without any of the other fluff. You can check out my Fat Controller CQRS Diet blog series as well as a related talk:

More

I plan on breaking down some of the misconceptions and other aspects that are often lumped in with CQRS in coming posts.

If you have any questions or comments, please let me know on twitter as I will focus my posts on those questions and comments.

Enjoy this post? Subscribe!

Subscribe to our weekly Newsletter and stay tuned.