Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AddAzureCosmosDB is not working with AddCosmosDbContext #7785

Open
1 task done
mwiedemeyer opened this issue Feb 26, 2025 · 8 comments
Open
1 task done

AddAzureCosmosDB is not working with AddCosmosDbContext #7785

mwiedemeyer opened this issue Feb 26, 2025 · 8 comments
Labels
area-integrations Issues pertaining to Aspire Integrations packages azure Issues associated specifically with scenarios tied to using Azure azure-cosmosdb Issues related to Azure CosmosDB
Milestone

Comments

@mwiedemeyer
Copy link

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

I have a very simple demo app here: /~https://github.com/mwiedemeyer/AspireDemo
Updated to Aspire 9.1

In the AppHost I add a CosmosDB resource with

var cosmos = builder.AddAzureCosmosDB("cosmos")
                    .RunAsPreviewEmulator(p => p.WithDataExplorer().WithDataVolume().WithLifetime(ContainerLifetime.Persistent))
                    .AddCosmosDatabase("db")
                    .AddContainer("users", "/id");

In my client a try to add a cosmos EF context with:

builder.AddCosmosDbContext<AppDbContext>("cosmos", "db");

However it fails, because it cannot find the connection string.

In the env variables of my client it shows only these connection strings mapping to the cosmos db:

  • Aspire__Microsoft__Azure__Cosmos__users__ConnectionString
  • users

The client fails with this error message:

'A DbContext could not be configured. Ensure valid connection information was provided in 'ConnectionStrings:cosmos' or either ConnectionString or AccountEndpoint must be provided in the 'Aspire:Microsoft:EntityFrameworkCore:Cosmos' or 'Aspire:Microsoft:EntityFrameworkCore:Cosmos:AppDbContext' configuration section.'

So the names do not match. Is there anything I need to do to fix it?
I also tried this one, but it fails either:

builder.AddCosmosDbContext<AppDbContext>("users", "db");

Expected Behavior

I expect the documented version to work like in the description above

Steps To Reproduce

Run the demo project from here /~https://github.com/mwiedemeyer/AspireDemo
Then open the console logs for the func and click on the link (something like http://localhost:7184/api/Function1)

Exceptions (if any)

InvalidOperationException

'A DbContext could not be configured. Ensure valid connection information was provided in 'ConnectionStrings:cosmos' or either ConnectionString or AccountEndpoint must be provided in the 'Aspire:Microsoft:EntityFrameworkCore:Cosmos' or 'Aspire:Microsoft:EntityFrameworkCore:Cosmos:AppDbContext' configuration section.'

.NET Version info

.NET SDK:
Version: 9.0.200
Commit: 90e8b202f2
Workload version: 9.0.200-manifests.c4f6226a
MSBuild version: 17.13.8+cbc39bea8

Anything else?

Aspire 9.1 just updated after the release yesterday. Working with Visual Studio.

@mwiedemeyer
Copy link
Author

Thanks a lot. I will try to find where the difference is. Maybe because I'm using a function app instead of a web app.
I will test it later and post an update here.

@eerhardt
Copy link
Member

We made a change in 9.1 that databases and containers act like SQL databases. They are child resources, which have names.

var cosmos = builder.AddAzureCosmosDB("cosmos")
                    .RunAsPreviewEmulator(p => p.WithDataExplorer().WithDataVolume().WithLifetime(ContainerLifetime.Persistent))
                    .AddCosmosDatabase("db")
                    .AddContainer("users", "/id");

the var cosmos is pointing to the container named "users". The Add methods in the AppHost adds a new resource and returns it.

https://learn.microsoft.com/en-us/dotnet/aspire/database/azure-cosmos-db-entity-framework-integration#add-azure-cosmos-db-database-and-container-resources

Change this to:

var cosmos = builder.AddAzureCosmosDB("cosmos")
    .RunAsPreviewEmulator(p => p.WithDataExplorer().WithDataVolume().WithLifetime(ContainerLifetime.Persistent));

cosmos.AddCosmosDatabase("db")
    .AddContainer("users", "/id");

@eerhardt
Copy link
Member

I think the problem here is that we missed the CosmosDB EF integration in Support named configuration providers for Aspire resources (dotnet/aspire#5826). Looking at that issue all the EF integrations are still unchecked, but the issue is closed.

@captainsafia - was this an oversight?

@eerhardt eerhardt added this to the 9.2 milestone Feb 26, 2025
@eerhardt eerhardt added the area-integrations Issues pertaining to Aspire Integrations packages label Feb 26, 2025
@mwiedemeyer
Copy link
Author

@eerhardt
Copy link
Member

Looking into this, I think there are 2 problems here.

  1. The CosmosDB Hosting code isn't putting the connection information in the right spot for the Cosmos EF client integration. It is only putting it in the right spot for the non-EF Cosmos client integration:

void IResourceWithAzureFunctionsConfig.ApplyAzureFunctionsConfiguration(IDictionary<string, object> target, string connectionName)
{
if (IsEmulator || UseAccessKeyAuthentication)
{
// Injected to support Azure Functions listener initialization.
target[connectionName] = ConnectionStringExpression;
// Injected to support Aspire client integration for CosmosDB in Azure Functions projects.
target[$"Aspire__Microsoft__Azure__Cosmos__{connectionName}__ConnectionString"] = ConnectionStringExpression;
}

The EF client integration looks in Aspire:Microsoft:EntityFrameworkCore:Cosmos:

private const string DefaultConfigSectionName = "Aspire:Microsoft:EntityFrameworkCore:Cosmos";

  1. The Cosmos EF client integration isn't reading the connection information from the "connectionName" location - related to what I said above with Support named configuration providers for Aspire resources (dotnet/aspire#5826. The EF client integrations appear to only read from the unnamed section, and a section named based on the DbContext type name:

var configurationSection = builder.Configuration.GetSection(defaultConfigSectionName);
bindSettings(settings, configurationSection);
var typeSpecificConfigurationSection = configurationSection.GetSection(typeof(TContext).Name);
if (typeSpecificConfigurationSection.Exists()) // /~https://github.com/dotnet/runtime/issues/91380
{
bindSettings(settings, typeSpecificConfigurationSection);
}

@eerhardt
Copy link
Member

eerhardt commented Feb 26, 2025

@mwiedemeyer - to workaround this problem, I was able to make your app work with changing the AppHost code to:

var builder = DistributedApplication.CreateBuilder(args);

var nosecret = builder.AddParameter("NoSecret");
var apiKey = builder.AddParameter("OpenAIApiKey", secret: true);

var cosmos = builder.AddAzureCosmosDB("cosmos")
                    .RunAsPreviewEmulator(p => p.WithDataExplorer().WithDataVolume().WithLifetime(ContainerLifetime.Persistent));
cosmos.AddCosmosDatabase("db")
    .AddContainer("users", "/id");

var sb = builder.AddAzureServiceBus("sb")
                    .RunAsEmulator(p => p.WithLifetime(ContainerLifetime.Persistent))
                    .AddServiceBusTopic("mytopic")
                    .AddServiceBusSubscription("sub1", "sub1");

builder.AddAzureFunctionsProject<Projects.AspireDemo>("func")
    .WithReference(cosmos)
    .WaitFor(cosmos)
    .WithReference(sb)
    .WaitFor(sb)
    .WithEnvironment("NoSecret", nosecret)
    .WithEnvironment("OpenAIApiKey", apiKey)
    .WithEnvironment(context =>
    {
        if (cosmos.Resource.IsEmulator || cosmos.Resource.UseAccessKeyAuthentication)
        {
            context.EnvironmentVariables["Aspire__Microsoft__EntityFrameworkCore__Cosmos__AppDbContext__ConnectionString"] = cosmos.Resource.ConnectionStringExpression;
        }
        else
        {
            context.EnvironmentVariables["Aspire__Microsoft__EntityFrameworkCore__Cosmos__AppDbContext__AccountEndpoint"] = cosmos.Resource.ConnectionStringExpression;
        }
    });

builder.Build().Run();

@mwiedemeyer
Copy link
Author

Awesome. Thank you.

@davidfowl davidfowl added azure Issues associated specifically with scenarios tied to using Azure azure-cosmosdb Issues related to Azure CosmosDB labels Feb 26, 2025
mwiedemeyer added a commit to mwiedemeyer/AspireDemo that referenced this issue Feb 27, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-integrations Issues pertaining to Aspire Integrations packages azure Issues associated specifically with scenarios tied to using Azure azure-cosmosdb Issues related to Azure CosmosDB
Projects
None yet
Development

No branches or pull requests

3 participants