Marrying CosmosDB and .NET Core
Cozy Saturday morning, I feel like writing some code. Have you read the title? I’ll try to keep it simple, but maybe stop on some key points about application structure/design. It’s more like not just tutorial, it’s more like conversation between us and technology.
If you are wondering what is .NET Core, it’s a new set of runtime, library and compiler components for creating web applications and services that run on Windows, Linux and Mac. Basically, it’s our old good .NET, but rewritten from scratch with a focus on modern things like performance, cloud-friendliness and so on and so forth. Moreover, it is fully open source!
And if talking about CosmosDB, it’s Microsoftie thing. Fully cloud, globally distributed, multi-model database.
What I like about it — your data is really globally replicated. With that you won’t ever care about replicating your data based on users location. It’s already automated and made right for you. And replicating data also means that is will be 100% available for the user, even if the server for his region will go down for some reason. Distribute your data, right?
And, as you see, it’s made totally in Microsoft-way: to get started you don’t need to dig into it, configure, write any code for that. Just press X. What I’ve learned from this kind of systems — with really simple interface for complex things — usually there is a lot of magic underhood. The simpler interface is, the more complicated things are underhood.
It’s really sick, check full description here.
Ok, let’s cut to the chase and get our hands dirty.
So I’m going to implement a simple console application without bells and whistles that will work with data from Azure CosmosDB. And since CosmosDB is multi-model, we will implement two ways of storing data — DocumentDB data MongoDB API. That’s basically what we do as software developers — work with data.
Let’s create a solution with .NET Core Console App in it.
As you see, I use C# Interactive windows, haven’t heard of it yet? You should definitely check it out!
What do you as .NET developer do when you are supposed to grab data from the database? Of course, you write a repository. And I’m no exception for that, I consider repository pattern as almost silver bullet for enterprise C# OOP.
But repository can be written in different ways. Let’s take a closer look.
Imagine we are working with Person with some Skills.
So casual IRepository would look like that:
And I’ve almost pressed that alt+enter on that!
Thinking about design, it’s pretty casual and I’ve been writing stuff like that since I was 16. But recently I’ve read a great blog post that discovered me that everything I’ve been doing was wrong. Not like totally wrong, but much. I thought I always do a really generic repository, but we need to go even deeper. Let’s go with that approach in our sample.
I wonder how it would look like in case we want to have something like GetAsync<T, TKey>(TKey id). And I tried to implement this on top of DocumentDB. Well, that wasn’t a very successful attempt, so let’s stick with this basic interface.
Everything you write in Clojure is a list.
Everything you write in C# is a repository.
OK, seems like our contract for repository is designed well, let’s put some meat on it.
What I also like about DocumentDb — it supports SQL syntax so you don’t lose your SQL skills, even though you are migrating from SQL to NoSQL.
MSDN always offered great documentation, so this topic is no exception — click & click. You can query your database right from C# code or from Azure Portal->Query Explorer. But there is one thing that is triggering me every time when I’m doing some SQL queries in Query Explorer: I’m very used to SQL Server Management Studio and I’m used to pressing F5 to run a query, but here it just refreshes the page T_T
As you see, there is no rocket science in the implementation, but it looks pretty legit.
Notice that static import: it’s my ad-hoc strongly typed configuration for .NET Core AppSettings.
I’ve written a simple shortcut for ReSharper(Live Template), quick look on automating routine work:
Moreover, it works like a charm!
Let’s step up to the MongoDb side.
Working with Mongo is the same as working in LINQ and good old EF, you don’t even need to change your code-style. What I like about Mongo implementation in Azure CosmosDb is that it use the standard official driver, not a custom one. So that allows me as developer to easily switch from e.g. cloud CosmosDb to local server or whatever I like without having to touch any code. There are a lot of things to say about Mongo as alternative way of storing data, but that’s not the key for now.
At this point, I’ve already tested both repositories and thought about creating one so called global repository. And here’s two options on creating it:
- Make a configuration flag like “Source” and check in code whether its value is “mongo” or “document” and, based on that flag, push to dedicated repository.
- Or to make a MainRepository that consists of all the repositories we have — mongo, documentdb, sql, w/e. And pushes to all these repositories, manually replicating data to absolutely different sources. And thinking about this scenario, I find it OK for logging purposes. Like you are inserting some data into your so to say data repository and after that, you insert metadata about this request and data itself into your log repository that is not dependent on data repository.
Anyways, that’s one more level of abstraction. That’s what I’ve discovered in myself when started doing a lot of programming — I’ve started thinking of things with some level of abstraction.
You see, articles like this might be useful to you. Not in case of the real need to implement a generic repository for CosmosDb, but to learn what you might need to learn or just to see how someone writes code. Have you ever watched someone writing a lot of code? Try that. You can’t become a good writer without having read any books written by other authors.
Just following tutorials never gives you skills that are required to be a successful developer. And I’m talking about planning things, organizing a project, discovering business needs and choosing proper tools for it, overcoming problems that will prevent you from successful delivering of project et cetera. Being a software developer is much more than simply writing code.
So I decided to go even deeper — have you ever heard of NPM, packaging things, high cohesion and loose coupling? In NPM every project you do is supposed to be a package,
Recently I’ve watched a great talk by Maarten Balliauw — creator of myGet — about NuGet beyond Hello World, I highly recommend you to do the same, his approach on viewing things in ABSOLUTELY non-packaged world of .NET is worth your time.
So I’ve polished it into separated packages, but unfortunately I didn’t achieve really clean loose coupling for all elements, but I think that packaging approach is very under-rated in .NET ecosystem, even through the whole .NET thing is moving to distributed/dockerized cloud architecture.
You thought referencing assemblies is old school?
Referencing projects is old school also now.
NuGet package references are the new black, especially since the new .NET is no more tied to Windows.
Definitely, take a look at Maarten’s talk, I’m sure it’s worth few hours of your time.
Mostly when I finish some of my big thoughts or pieces of work, I feel like I’m Michael Jordan back in ’96, ’97.
So what we have left: two really generic repositories for Azure CosmosDb and packaged loosely coupled console application.
And if you were that brave to scroll till here, you deserved to have a GitHub link to this project, here you go!
I’m very likely to add some distributed messaging (e.g RabbitMQ || Event Bus) someday to this application, just to keep this solution as a playground for implementing enterprise patterns. But that’s all for today!
Come back later for another piece of cake :)