Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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 @@ -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