Entity Framework Core (EF Core) was designed to not being a framework for only relational databases. It just takes some time to get the first non-relational providers. Now is the time.
Microsoft now has the first preview for an EF Core provider for Cosmos DB. With this I have to do my first experiments using Cosmos DB from EF Core.
Updated to Entity Framework Core 2.2 Preview 3
Azure Cosmos DB
Azure Cosmos DB is a NoSQL database from Microsoft. It is globally distributed and offers multiple models. You can store data with key/values pairs, records with multiple columns (table storage), documents, and data linked within graphs. If you need massive amounts of data, reads, and writes with fast responses and high throughput, Azure Cosmos DB gives you great options.
EF Core Providers
Available EF Core providers are listed in the document Database Providers. The provider I’m using most of the time is of course the provider for SQL Server. There are some other providers as well, e.g. from Microsoft for SQLite, and in-memory. From the Npgsql Development Team you can get a provider for PostreSQL. MySQL and MariaDB providers are from the Pomelo Foundation Project. Erik Ejlskov Jensen created a provider for SQL Server Compact. Oracle offers a provider for MySQL. Jiří Činčura and Rafael Almeida have providers for Firebird. IBM is in the game with providers for Db2 and Informix. Paid high quality providers for Oracle, PostgreSQL, SQLite, and MySQL are from DevArt. There’s even one for Microsoft Access from Bubi.
Missing are Non-SQL providers, and an Oracle provider from Oracle. Oracle already has a Statement of Direction for .NET Core and Entity Framework Core, so a provider from Oracle is coming soon. Oracle is not left out as there’s a provider from DevArt as previously mentioned. Microsoft now has a sample provider for Oracle as well, but this one has some limitations.
With NoSQL Providers, Microsoft started to work on a Azure Table Storage provider. Because of time constraints, this was delayed. Now the Cosmos DB provider has a bigger focus. Preview 3 for Microsoft.EntityFrameworkCore.Cosmos is now available on the NuGet server.
To start, I’m creating a .NET Core 2.2 console application and adding these packages:
From the first preview, the name of the provider package changed from Microsoft.EntityFrameworkCore.Cosmos.Sql to Microsoft.EntityFrameworkCore.Cosmos.
The configuration for the Cosmos DB is read from a JSON configuration file. I’m not storing the secret key in the source code repository. Instead, app secrets are used during development time with the package Microsoft.Extensions.Configuration.UserSecrets.
The EF Core context is instantiated by using dependency injection, that’s why the package Microsoft.Extensions.DependencyInjection is added. EF Core could be used without creating a DI container. However as in all production apps I’m creating nowadays I’m using a DI container, I’m using it with this small sample as well.
For logging I’m using the
ILogger interface, to see what information is traced by the EF Core provider – that’s the reason for the Microsoft.Extensions.Logging.Debug package.
.NET Core 2.2 is in preview at the time of this writing, and can be downloaded from the .NET Core 2.2 downloads.
The project file for the sample app lists the packages:
Creating Azure Cosmos DB
Before building the application, I’m creating a new Azure Cosmos DB account:
Creating an Azure Cosmos DB account, you need to decide and select one of the APIs:
- Azure Table
- Gremlin (graph)
Azure Cosmos DB offers different storage technologies, such as JSON documents, table storage, and storing relations using a graph API. SQL is the successor of DocumentDB, and this is where this new provider can be used.
To access this account from the provider, from the portal the URI and the key is needed. All this information can be accessed by selecting the Keys settings from the portal.
I’m adding the service endpoint from the Azure Cosmos DB account and a database name to the JSON configuration file
I’m not directly adding the key to the JSON configuration file, but instead use app secrets. Because an identifier for app secrets (
UserSecretsId) was added to
CosmosDBWithEFCore.csproj, and the NuGet package
Microsoft.Extensions.Configuration.UserSecrets was added, the dotnet CLI can be used to configure the authentication key:
dotnet user-secrets set CosmosSettings:AuthKey "add your auth-key from Azure Cosmos DB"
EF Core Context and Model and Services
Next, I’m creating the EF Core context and the model. The model is defined with the
Book class and simple properties:
The EF Core
BooksContext does not differ to other EF Core contexts that are used with SQL Server:
BooksService is used to read and write
Book objects. It’s not different to other services using an EF Core context. With the constructor, the
BooksContext is injected. This context is used when creating the database, adding new
Book objects, and creating a query to read the
First I tried to create the database and the collection in the portal. However, I didn’t see how to map the names at first, and documentation was not existing yet. It turned out that creating the database directly from EF Core is already working which helped finding the default database name.
The dependency injection container is configured in the
Program class. Having the NuGet package for the EF Core provider for Azure Cosmos DB referenced, allows using the
UseCosmos extension method. This method needs the configuration for the service endpoint, the key, and the database name. These settings are coming from
appsettings.json, and the app secrets.
Main method just connects everything together. First, the DI container is configured. The
BooksService is returned from the container to a) create the database, b) write book records, and to c) query books.
Running the App
Running the app results in creation of the database with the name passed to the
UseCosmos method, and the collection with the name of the context. You can see this in the Azure Portal.
Using the Azure Cosmos DB Data Explorer, you can see all the book objects created.
With the collection name, you can change a different default, or assign a collection name for an entity using the
Accessing Azure Cosmos DB generated values
A book is represented within Cosmos DB with the properties defined in the model, and some additional properties used by Azure Cosmos DB:
Here’s some information about these values:
- etag – This is the resource etag, required for optimistic concurrency. This value is changed with every update.
- id – A unique name with a max length of 255 characters. This value, must be set on insert, and be unique within the database. Using EF Core, it has the same value as specified by the key in the model.
- rid – This is a system generated hierarchical unique identifier, and used for navigation.
- ts – The timestamp shows the last update time.
- self – An addressable url to the document.
- attachment – Documents can have attachments. This value gives references to attachment resources.
The type of the class is stored with the Discriminator value. Don’t be tempted to use different collections for every type. You can save different types in the same collection. Retrieving objects on the type is fast, this information is indexed. Calculate costs for Azure Cosmos DB per collection.
Using EF Core, you can either add properties to your model to retrieve these values, or create shadow properties in the context definition.
These shadow properties can be retrieved using the
Entry method of the
This just have been the first experiments using Azure Cosmos DB using the new EF Core provider. Azure Cosmos DB integrates nicely into EF Core. You’re creating the models and the context as you are used to, and can create the database, write documents, and create queries.
Additional properties such as the etag and self implemented by Azure Cosmos DB do not need to be part of your model, but can be easily retrieved using the shadow properties from EF Core.
Expect more information on EF Core and Azure Cosmos DB to come in the following months.
If you’ve read this far, consider buying me a coffee which helps me staying up longer and writing more articles.
Enjoy learning and programming!