It's here! Well, nearly...
I've been eagerly awaiting the release of the Cosmos DB SQL Provider in EF Core. I'm working on a couple of projects at the moment which use ASP.NET Core, Azure Functions, Azure SQL and Cosmos DB - and while using the Document Client directly works very well & is straightforward, I'd rather keep things consistent and use Entity Framework for both SQL and Cosmos DB.
I love the way Microsoft has been moving more of its development into the open. I keep tabs on several repos on Github, including the EF Core one, and I noticed the other day that there had been some activity on the "cosmossqlprovider" branch. And then I saw this...
And then this...
Hmm. Now, I'm pretty impatient...so rather than waiting for the team to merge, I started to wonder whether I could get this working myself.
So, first step was to clone the repo. I did a quick 'git checkout cosmossqlprovider', made sure everything looked ok, then checked out master again before running 'git merge cosmossqlprovider'. No conflicts, as per the pull request details on Github. Awesome.
I had to dive into the code a bit to figure out how to get this working in an ASP.NET Core app, and after a bit of work I had it all working...nearly. Unfortunately, every time I tried to save an entity I kept getting a "Method not found" error.
After banging my head against this for a while I thought I'd see if I could get the code working against the current .NET Core version instead.
I created a new solution and copied the EFCore.Cosmos.SQL project into this directory (note - you also need the "src\shared" folder as well).
I then edited the EFCore.Cosmos.SQL.csproj file from this...
(Note: I had to set the LangVersion to "latest")
And it builds!
Ok, great. So next step is to create a project which uses this. First of all, I created a simple ASP.NET Core Web API project, added a reference to the EFCore.Cosmos.SQL project, and then created an Entities folder with a simple test Entity & DbContext. From poking around in the code I saw that my entities needed a "CollectionName" annotation, and I added this via the Fluent API. I'm just using a collection named 'items', which I already have created.
I ended up with these:
And then hooked it all up in the Startup.cs file as below:
I'd suggest using the Azure Cosmos DB Emulator for local development, available from here.
As a quick test, I'm just editing the ValuesController Get method, adding the following code:
And...it works! Opening up the Data Explorer for the Cosmos DB Emulator shows us the entity, now in document form:
There are a few interesting things here (that took a bit of trial and error to figure out!). Firstly, I needed to define a primary id key, otherwise it throws an error. I used "Id" at first, but it created a document with both "Id" and "id" fields, so I switched to just a lowercase "id" property. Secondly, from what I've seen, JsonProperty annotations don't do anything - so your documents are stored with capitalised properties. Which makes sense, you can now have nice clean POCO entities without having the JsonProperty annotations all over them. Thirdly, there is a "Discriminator" column defined, with the entity name in it. More on that in the next post...
That was a very quick first look - in the next post I'll look at related entities and also give it a try with Azure Functions using the awesome FunctionMonkey library.