Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/Aspire.Hosting.Azure.CosmosDB/AzureCosmosDBResource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,15 @@ void IResourceWithAzureFunctionsConfig.ApplyAzureFunctionsConfiguration(IDiction
target[connectionName] = ConnectionStringExpression;
// Injected to support Aspire client integration for CosmosDB in Azure Functions projects.
target[$"Aspire__Microsoft__Azure__Cosmos__{connectionName}__ConnectionString"] = ConnectionStringExpression;
target[$"Aspire__Microsoft__EntityFrameworkCore__Cosmos__{connectionName}__ConnectionString"] = ConnectionStringExpression;
}
else
{
// Injected to support Azure Functions listener initialization.
target[$"{connectionName}__accountEndpoint"] = ConnectionStringExpression;
// Injected to support Aspire client integration for CosmosDB in Azure Functions projects.
target[$"Aspire__Microsoft__Azure__Cosmos__{connectionName}__AccountEndpoint"] = ConnectionStringExpression;
target[$"Aspire__Microsoft__EntityFrameworkCore__Cosmos__{connectionName}__AccountEndpoint"] = ConnectionStringExpression;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public static class AspireAzureEFCoreCosmosExtensions

var settings = builder.GetDbContextSettings<TContext, EntityFrameworkCoreCosmosSettings>(
DefaultConfigSectionName,
connectionName,
(settings, section) => section.Bind(settings)
);

Expand Down Expand Up @@ -131,6 +132,7 @@ void UseCosmosBody(CosmosDbContextOptionsBuilder builder)

var settings = builder.GetDbContextSettings<TContext, EntityFrameworkCoreCosmosSettings>(
DefaultConfigSectionName,
null,
(settings, section) => section.Bind(settings)
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
namespace Microsoft.Extensions.Hosting;

/// <summary>
/// Extension methods for configuring EntityFrameworkCore DbContext to Azure SQL, MS SQL server
/// Extension methods for configuring EntityFrameworkCore DbContext to Azure SQL, MS SQL server
/// </summary>
public static class AspireSqlServerEFCoreSqlClientExtensions
{
Expand Down Expand Up @@ -47,6 +47,7 @@ public static class AspireSqlServerEFCoreSqlClientExtensions

var settings = builder.GetDbContextSettings<TContext, MicrosoftEntityFrameworkCoreSqlServerSettings>(
DefaultConfigSectionName,
connectionName,
(settings, section) => section.Bind(settings)
);

Expand Down Expand Up @@ -100,6 +101,7 @@ void ConfigureDbContext(DbContextOptionsBuilder dbContextOptionsBuilder)

var settings = builder.GetDbContextSettings<TContext, MicrosoftEntityFrameworkCoreSqlServerSettings>(
DefaultConfigSectionName,
null,
(settings, section) => section.Bind(settings)
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ public static partial class AspireEFPostgreSqlExtensions

var settings = builder.GetDbContextSettings<TContext, NpgsqlEntityFrameworkCorePostgreSQLSettings>(
DefaultConfigSectionName,
connectionName,
(settings, section) => section.Bind(settings)
);

Expand Down Expand Up @@ -112,6 +113,7 @@ void ConfigureDbContext(DbContextOptionsBuilder dbContextOptionsBuilder)

var settings = builder.GetDbContextSettings<TContext, NpgsqlEntityFrameworkCorePostgreSQLSettings>(
DefaultConfigSectionName,
null,
(settings, section) => section.Bind(settings)
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
namespace Microsoft.Extensions.Hosting;

/// <summary>
/// Extension methods for configuring EntityFrameworkCore DbContext to Oracle database
/// Extension methods for configuring EntityFrameworkCore DbContext to Oracle database
/// </summary>
public static class AspireOracleEFCoreExtensions
{
Expand Down Expand Up @@ -48,6 +48,7 @@ public static class AspireOracleEFCoreExtensions

var settings = builder.GetDbContextSettings<TContext, OracleEntityFrameworkCoreSettings>(
DefaultConfigSectionName,
connectionName,
(settings, section) => section.Bind(settings)
);

Expand Down Expand Up @@ -99,6 +100,7 @@ void ConfigureDbContext(DbContextOptionsBuilder dbContextOptionsBuilder)

var settings = builder.GetDbContextSettings<TContext, OracleEntityFrameworkCoreSettings>(
DefaultConfigSectionName,
null,
(settings, section) => section.Bind(settings)
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public static partial class AspireEFMySqlExtensions

var settings = builder.GetDbContextSettings<TContext, PomeloEntityFrameworkCoreMySqlSettings>(
DefaultConfigSectionName,
connectionName,
(settings, section) => section.Bind(settings)
);

Expand Down Expand Up @@ -149,6 +150,7 @@ void ConfigureDbContext(IServiceProvider serviceProvider, DbContextOptionsBuilde

var settings = builder.GetDbContextSettings<TContext, PomeloEntityFrameworkCoreMySqlSettings>(
DefaultConfigSectionName,
null,
(settings, section) => section.Bind(settings)
);

Expand Down
10 changes: 9 additions & 1 deletion src/Components/Common/EntityFrameworkUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,20 @@ internal static class EntityFrameworkUtils
/// <summary>
/// Binds the DbContext specific configuration section to settings when available.
/// </summary>
public static TSettings GetDbContextSettings<TContext, TSettings>(this IHostApplicationBuilder builder, string defaultConfigSectionName, Action<TSettings, IConfiguration> bindSettings)
public static TSettings GetDbContextSettings<TContext, TSettings>(this IHostApplicationBuilder builder, string defaultConfigSectionName, string? connectionName, Action<TSettings, IConfiguration> bindSettings)
where TSettings : new()
{
TSettings settings = new();
var configurationSection = builder.Configuration.GetSection(defaultConfigSectionName);
bindSettings(settings, configurationSection);
// If the connectionName is not provided, we've been called in the context
// of an Enrich invocation and don't need to bind the connectionName specific settings.
// Instead, we'll just bind to the TContext-specific settings.
if (connectionName is not null)
{
var connectionSpecificConfigurationSection = configurationSection.GetSection(connectionName);
bindSettings(settings, connectionSpecificConfigurationSection);
}
var typeSpecificConfigurationSection = configurationSection.GetSection(typeof(TContext).Name);
if (typeSpecificConfigurationSection.Exists()) // https://github.com/dotnet/runtime/issues/91380
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,18 +117,21 @@ public void AzureCosmosDBAppliesAzureFunctionsConfiguration()
((IResourceWithAzureFunctionsConfig)cosmos.Resource).ApplyAzureFunctionsConfiguration(target, "cosmos");
Assert.Collection(target.Keys.OrderBy(k => k),
k => Assert.Equal("Aspire__Microsoft__Azure__Cosmos__cosmos__AccountEndpoint", k),
k => Assert.Equal("Aspire__Microsoft__EntityFrameworkCore__Cosmos__cosmos__AccountEndpoint", k),
k => Assert.Equal("cosmos__accountEndpoint", k));

target.Clear();
((IResourceWithAzureFunctionsConfig)db1.Resource).ApplyAzureFunctionsConfiguration(target, "db1");
Assert.Collection(target.Keys.OrderBy(k => k),
k => Assert.Equal("Aspire__Microsoft__Azure__Cosmos__db1__AccountEndpoint", k),
k => Assert.Equal("Aspire__Microsoft__EntityFrameworkCore__Cosmos__db1__AccountEndpoint", k),
k => Assert.Equal("db1__accountEndpoint", k));

target.Clear();
((IResourceWithAzureFunctionsConfig)container1.Resource).ApplyAzureFunctionsConfiguration(target, "container1");
Assert.Collection(target.Keys.OrderBy(k => k),
k => Assert.Equal("Aspire__Microsoft__Azure__Cosmos__container1__AccountEndpoint", k),
k => Assert.Equal("Aspire__Microsoft__EntityFrameworkCore__Cosmos__container1__AccountEndpoint", k),
k => Assert.Equal("container1__accountEndpoint", k));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,60 @@ public void AddAzureCosmosClient_FailsWithError()
Assert.Contains("AccountEndpoint", e.Message);
}

[Fact]
public void AddCosmosDbContext_WithConnectionNameAndSettings_AppliesConnectionSpecificSettings()
{
var builder = Host.CreateEmptyApplicationBuilder(null);

var connectionName = "testdb";
var databaseName = "testdbname";

builder.Configuration.AddInMemoryCollection(new Dictionary<string, string?>
{
[$"ConnectionStrings:{connectionName}"] = ConnectionString,
[$"Aspire:Microsoft:EntityFrameworkCore:Cosmos:{connectionName}:RequestTimeout"] = "60",
[$"Aspire:Microsoft:EntityFrameworkCore:Cosmos:{connectionName}:DisableTracing"] = "true"
});

EntityFrameworkCoreCosmosSettings? capturedSettings = null;
builder.AddCosmosDbContext<TestDbContext>(connectionName, databaseName, settings =>
{
capturedSettings = settings;
});

Assert.NotNull(capturedSettings);
Assert.Equal(TimeSpan.Parse("60"), capturedSettings.RequestTimeout);
Assert.True(capturedSettings.DisableTracing);
}

[Fact]
public void AddCosmosDbContext_WithConnectionSpecificAndContextSpecificSettings_PrefersContextSpecific()
{
// Arrange
var builder = Host.CreateEmptyApplicationBuilder(null);

var connectionName = "testdb";
var databaseName = "testdbname";

builder.Configuration.AddInMemoryCollection(new Dictionary<string, string?>
{
[$"ConnectionStrings:{connectionName}"] = ConnectionString,
// Connection-specific settings
[$"Aspire:Microsoft:EntityFrameworkCore:Cosmos:{connectionName}:RequestTimeout"] = "60",
// Context-specific settings wins
[$"Aspire:Microsoft:EntityFrameworkCore:Cosmos:TestDbContext:RequestTimeout"] = "120"
});

EntityFrameworkCoreCosmosSettings? capturedSettings = null;
builder.AddCosmosDbContext<TestDbContext>(connectionName, databaseName, settings =>
{
capturedSettings = settings;
});

Assert.NotNull(capturedSettings);
Assert.Equal(TimeSpan.Parse("120"), capturedSettings.RequestTimeout);
}

private static void PopulateConfiguration(ConfigurationManager configuration, string connectionString) =>
configuration.AddInMemoryCollection([
new KeyValuePair<string, string?>("ConnectionStrings:cosmos", connectionString)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,58 @@ public void DoesntThrowWhenDbContextIsRegisteredBeforeAspireComponentProduction(
Assert.Null(exception);
}

[Fact]
public void AddSqlServerDbContext_WithConnectionNameAndSettings_AppliesConnectionSpecificSettings()
{
var builder = Host.CreateEmptyApplicationBuilder(null);

var connectionName = "testdb";

builder.Configuration.AddInMemoryCollection(new Dictionary<string, string?>
{
[$"ConnectionStrings:{connectionName}"] = ConnectionString,
[$"Aspire:Microsoft:EntityFrameworkCore:SqlServer:{connectionName}:CommandTimeout"] = "60",
[$"Aspire:Microsoft:EntityFrameworkCore:SqlServer:{connectionName}:DisableTracing"] = "true"
});

MicrosoftEntityFrameworkCoreSqlServerSettings? capturedSettings = null;
builder.AddSqlServerDbContext<TestDbContext>(connectionName, settings =>
{
capturedSettings = settings;
});

Assert.NotNull(capturedSettings);
Assert.Equal(60, capturedSettings.CommandTimeout);
Assert.True(capturedSettings.DisableTracing);
}

[Fact]
public void AddSqlServerDbContext_WithConnectionSpecificAndContextSpecificSettings_PrefersContextSpecific()
{
// Arrange
var builder = Host.CreateEmptyApplicationBuilder(null);

var connectionName = "testdb";

builder.Configuration.AddInMemoryCollection(new Dictionary<string, string?>
{
[$"ConnectionStrings:{connectionName}"] = ConnectionString,
// Connection-specific settings
[$"Aspire:Microsoft:EntityFrameworkCore:SqlServer:{connectionName}:CommandTimeout"] = "60",
// Context-specific settings wins
[$"Aspire:Microsoft:EntityFrameworkCore:SqlServer:TestDbContext:CommandTimeout"] = "120"
});

MicrosoftEntityFrameworkCoreSqlServerSettings? capturedSettings = null;
builder.AddSqlServerDbContext<TestDbContext>(connectionName, settings =>
{
capturedSettings = settings;
});

Assert.NotNull(capturedSettings);
Assert.Equal(120, capturedSettings.CommandTimeout);
}

public class TestDbContext2 : DbContext
{
public TestDbContext2(DbContextOptions<TestDbContext2> options) : base(options)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,62 @@ public void DoesntThrowWhenDbContextIsRegisteredBeforeAspireComponentProduction(
Assert.Null(exception);
}

[Fact]
public void AddNpgsqlDbContext_WithConnectionNameAndSettings_AppliesConnectionSpecificSettings()
{
var builder = Host.CreateEmptyApplicationBuilder(null);

var connectionName = "testdb";

builder.Configuration.AddInMemoryCollection(new Dictionary<string, string?>
{
[$"ConnectionStrings:{connectionName}"] = ConnectionString,
[$"Aspire:Npgsql:EntityFrameworkCore:PostgreSQL:{connectionName}:CommandTimeout"] = "60",
[$"Aspire:Npgsql:EntityFrameworkCore:PostgreSQL:{connectionName}:DisableRetry"] = "true",
[$"Aspire:Npgsql:EntityFrameworkCore:PostgreSQL:{connectionName}:DisableHealthChecks"] = "true"
});

builder.AddNpgsqlDbContext<TestDbContext>(connectionName);

NpgsqlEntityFrameworkCorePostgreSQLSettings? capturedSettings = null;
builder.AddNpgsqlDbContext<TestDbContext>(connectionName, settings =>
{
capturedSettings = settings;
});

Assert.NotNull(capturedSettings);
Assert.Equal(60, capturedSettings.CommandTimeout);
Assert.True(capturedSettings.DisableRetry);
Assert.True(capturedSettings.DisableHealthChecks);
}

[Fact]
public void AddNpgsqlDbContext_WithConnectionSpecificAndContextSpecificSettings_PrefersContextSpecific()
{
// Arrange
var builder = Host.CreateEmptyApplicationBuilder(null);

var connectionName = "testdb";

builder.Configuration.AddInMemoryCollection(new Dictionary<string, string?>
{
[$"ConnectionStrings:{connectionName}"] = ConnectionString,
// Connection-specific settings
[$"Aspire:Npgsql:EntityFrameworkCore:PostgreSQL:{connectionName}:CommandTimeout"] = "60",
// Context-specific settings wins
[$"Aspire:Npgsql:EntityFrameworkCore:PostgreSQL:TestDbContext:CommandTimeout"] = "120"
});

NpgsqlEntityFrameworkCorePostgreSQLSettings? capturedSettings = null;
builder.AddNpgsqlDbContext<TestDbContext>(connectionName, settings =>
{
capturedSettings = settings;
});

Assert.NotNull(capturedSettings);
Assert.Equal(120, capturedSettings.CommandTimeout);
}

public class TestDbContext2 : DbContext
{
public TestDbContext2(DbContextOptions<TestDbContext2> options) : base(options)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,58 @@ public void CanPassSettingsToDbContext()
Assert.NotNull(context);
}

[Fact]
public void AddOracleDatabaseDbContext_WithConnectionNameAndSettings_AppliesConnectionSpecificSettings()
{
var builder = Host.CreateEmptyApplicationBuilder(null);

var connectionName = "testdb";

builder.Configuration.AddInMemoryCollection(new Dictionary<string, string?>
{
[$"ConnectionStrings:{connectionName}"] = ConnectionString,
[$"Aspire:Oracle:EntityFrameworkCore:{connectionName}:CommandTimeout"] = "60",
[$"Aspire:Oracle:EntityFrameworkCore:{connectionName}:DisableTracing"] = "true"
});

OracleEntityFrameworkCoreSettings? capturedSettings = null;
builder.AddOracleDatabaseDbContext<TestDbContext>(connectionName, settings =>
{
capturedSettings = settings;
});

Assert.NotNull(capturedSettings);
Assert.Equal(60, capturedSettings.CommandTimeout);
Assert.True(capturedSettings.DisableTracing);
}

[Fact]
public void AddOracleDatabaseDbContext_WithConnectionSpecificAndContextSpecificSettings_PrefersContextSpecific()
{
// Arrange
var builder = Host.CreateEmptyApplicationBuilder(null);

var connectionName = "testdb";

builder.Configuration.AddInMemoryCollection(new Dictionary<string, string?>
{
[$"ConnectionStrings:{connectionName}"] = ConnectionString,
// Connection-specific settings
[$"Aspire:Oracle:EntityFrameworkCore:{connectionName}:CommandTimeout"] = "60",
// Context-specific settings wins
[$"Aspire:Oracle:EntityFrameworkCore:TestDbContext:CommandTimeout"] = "120"
});

OracleEntityFrameworkCoreSettings? capturedSettings = null;
builder.AddOracleDatabaseDbContext<TestDbContext>(connectionName, settings =>
{
capturedSettings = settings;
});

Assert.NotNull(capturedSettings);
Assert.Equal(120, capturedSettings.CommandTimeout);
}

public class TestDbContext2 : DbContext
{
public TestDbContext2(DbContextOptions<TestDbContext2> options) : base(options)
Expand Down
Loading
Loading