I've integrated Cosmos DB in my ASP.NET Core API project, using the latest EF Core package that ships with a Cosmos DB provider.
I'm able to successfully use this provider when running locally in my local ASF cluster, connecting to a local Cosmos DB emulator instance. However, when trying to either run in local ASF or Azure-hosted ASF, I'm unable to connect to the Azure Cosmos DB instance. For some reason I keep getting a 400 BadRequest when initializing the seed for the database/collection.
It's the following line that is generating an error:
var created = await context.Database.EnsureCreatedAsync();
Exception:
BadRequest at Microsoft.EntityFrameworkCore.Cosmos.Storage.Internal.CosmosClient.CreateDocumentCollectionIfNotExistsOnceAsync(DbContext _, String collectionId, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.ExecuteImplementationAsync[TState,TResult](Func4 operation, Func
4 verifySucceeded, TState state, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.ExecuteImplementationAsync[TState,TResult](Func4 operation, Func
4 verifySucceeded, TState state, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Cosmos.Storage.Internal.CosmosDatabaseCreator.EnsureCreatedAsync(CancellationToken cancellationToken) at Infrastructure.SystemDataContextSeed.SeedAsync(SystemDataContext context) in Infrastructure\SystemDataContextSeed.cs:line 21 at xtensions.IWebHostExtensions.Seed(IWebHost webhost) in Extensions\IWebHostExtensions.cs:line 23 at Api.<>c__DisplayClass1_0.b__1(String url, AspNetCoreCommunicationListener listener) in AccountApi.cs:line 47 at Microsoft.ServiceFabric.Services.Communication.AspNetCore.AspNetCoreCommunicationListener.OpenAsync(CancellationToken cancellationToken) at Microsoft.ServiceFabric.Services.Runtime.StatelessServiceInstanceAdapter.OpenCommunicationListenersAsync(CancellationToken cancellationToken)
What I've tried:
The endpoint details used are in the form of:
"Cosmos": {
"EndPoint": "https://xxxx-sqlapi.documents.azure.com:443",
"AuthKey": "xxx==",
"DatabaseName": "AccountService"
},
Extension method to hook up the Cosmos DB provider:
public static IServiceCollection AddCosmosSettings(this IServiceCollection services, IConfiguration configuration)
{
services.AddEntityFrameworkCosmos()
.AddDbContext<SystemDataContext>(options =>
{
options.UseCosmos(configuration["Cosmos:EndPoint"], configuration["Cosmos:AuthKey"], configuration["Cosmos:DatabaseName"]); ;
},
ServiceLifetime.Scoped //Showing explicitly that the DbContext is shared across the HTTP request scope (graph of objects started in the HTTP request)
);
return services;
}
Any ideas are greatly appreciated!
For reference, the Cosmos DB provider in EF Core 2.2 is a preview, and is not suitable for use against an Azure-hosted Cosmos DB. This is because in some places, headers are missing that are apparently not an issue for the emulator, but cause a 400 when exeuting against Azure.
The issue I was looking at the longest, was the fact that I got a 400 when it was trying to create the document collection. After digging in the EF Core sourcecode, I saw that it did not sent any partition keys. There is actually no implementation of partition keys at all in the current Cosmos DB implementation. And because I created a database in Azure with shared throughput across collections, you are required to provide a partition key on collection level apparently.