Event Sourcing with SQL Stream Store
Tags: dotnet, eventsourcing, dotnetcore
Published: 2019-09-12 01:28:10

---
title: Event Sourcing with SQL Stream Store
published: true
tags: dotNET,EventSourcing,dotnetcore
canonical_url: https://codeopinion.com/event-sourcing-with-sql-stream-store/
---

![Event Sourcing with SQL Stream Store](https://codeopinion.com/wp-content/uploads/2017/11/Numismatics_and_Notaphily_icon-300x216.png)

I’ve known about SQL Stream Store for a bit (I believe when it was called Cedar) but haven’t really looked into it much. The premise is to provide a stream store over SQL. Currently supporting MS SQL Server, PostgreSQL, and MySQL. Meaning it is simply a .NET Library you can use with an SQL implementation. Let’s take a look at how you can implement Event Sourcing with SQL Stream Store.

## SQL Stream Store Demo Application

For this demo/sample, I’m going to create a .NET Core 3 console app. The idea will be to create the stereotypical event-sourcing example of a bank account.

I wanted to explore the primary functions needed of an event stream.

- Create a Stream
- Append a new Event to a Stream
- Read Events from a Stream
- Subscribe to a Stream to receive appended Events

## NuGet Package

As always, the first thing is to get the **SqlStreamStore** [NuGet Package](https://www.nuget.org/packages/SqlStreamStore) by adding it as a PackageReference in your csproj.

{% gist https://gist.github.com/dcomartin/dde6eb7336b909e867a07536f38abae8 %}

I’ve also included Newtonsoft.Json because I’m going to be (de)serializing events.

## Events

I’m going to create two events to represent the bank account transactions. **Deposited** and **Withdrawn**. Both of these will extend the abstract **AccountEvent** that will contain the TransactionId, Dollar Amount, and DateTime of the event.

{% gist https://gist.github.com/dcomartin/fac64044da03bb66c2bdf0c18684b6dc %}

## Creating a Stream

There is no way of creating an empty stream. This is actually really nice. Instead when appending an event to a stream, if the stream does not already exist, it’s created. This is the same how [EventStore](https://eventstore.org/) works and should also feel familiar in comparison to the API.

## Appending to a Stream

Appending a new event to a stream is pretty straight forward. From the **IStreamStore** there is an **AppendToStream** method that takes a few args.

The first is **StreamId**. This generally would represent your aggregate root ID. In this demo, I’m setting it Account:{GUID}.

The second arg is **ExpectedVersion**. This is also similar to the EventStore API. This is used for handling concurrency. You can specify an integer that represents the number of events that are persisted in the stream. You can also use the **ExpectedVersion** enum that can specify **Any** to not concern yourself with concurrency or **NoStream** to verify its the first event.

Finally, the 3rd param is an instance of **NewStreamMessage**. It contains the MessageId (GUID), an event name and the event json body.

An interesting takeaway here is the event name is intentionally made as a string so you are not serializing/deserializing to the CRL type name. This is a great idea since the CLR type name is likely to be changed more than just a plain string which you can keep constant.

{% gist https://gist.github.com/dcomartin/5171076c2ef540fe63db8751fd4652bc %}

## Reading a Stream

You can read a stream forward or backward. Forward meaning from the very first event until the last, which is what I’ll use in this example.

You simply specify the **StreamId** , the starting version (0) and how many events to pull from the stream. The result contains an **IsEnd** to indicate there are no more events left in the stream to read.

{% gist https://gist.github.com/dcomartin/3f35710c50c9fa57f4a7275b189f326f %}

## Subscribing to a Stream

Subscribing to a stream is pretty straight forward. Specify the **StreamId** , the starting version/position of where you want to be notified of new events from, and then **StreamMessageReceived** for handling the newly appended event.

{% gist https://gist.github.com/dcomartin/0611ee53cf8b5ed83cbe3f2c0ec6ddf8 %}

## Wrapping it up

Now that I’ve covered all the primary aspects, it’s just a matter of adding some input/output to our console app by allowing the user to deposit and withdrawal from the account.

In the demo, I’m using the **InMemoryStreamStore** so there is no persisted data upon restarting the app. I’m also using a new GUID to represent the AccountId on each run.

{% gist https://gist.github.com/dcomartin/744c8c6c536a82bd27f312844c7d3775 %}

## Source Code

All the [source code](https://github.com/dcomartin/SqlStreamStore.Demo) shown in this post is available on GitHub.

This was a quick look at just a few of the APIs in SQL Stream Store but should give you a feel for how it works.

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

[https://github.com/dcomartin/SqlStreamStore.Demo](https://github.com/dcomartin/SqlStreamStore.Demo)

Related Links:

- [EventStore for Orleans Grain Persistence](https://codeopinion.com/eventstore-for-orleans-grain-persistence/)
- [EventStore Persistent Subscriptions Demo](https://codeopinion.com/event-store-persistent-subscriptions-demo/)

[Follow @codeopinion](https://twitter.com/codeopinion?ref_src=twsrc%5Etfw)

The post [Event Sourcing with SQL Stream Store](https://codeopinion.com/event-sourcing-with-sql-stream-store/) appeared first on [CodeOpinion](https://codeopinion.com).