From 0a1d0ac5d4f1965ed5c7e04cf2571a1fd40e761f Mon Sep 17 00:00:00 2001 From: Bruno Ferreira Date: Wed, 13 May 2026 11:58:45 -0300 Subject: [PATCH 1/7] fix: handle wildcard '*' in --context parameter for UpdateDatabase and MigrationsBundle --- .../Design/Internal/MigrationsOperations.cs | 23 +++++++++++++++++++ .../Internal/MigrationsOperationsTest.cs | 17 ++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/EFCore.Design/Design/Internal/MigrationsOperations.cs b/src/EFCore.Design/Design/Internal/MigrationsOperations.cs index 1410f4b875d..93ffc6ec61f 100644 --- a/src/EFCore.Design/Design/Internal/MigrationsOperations.cs +++ b/src/EFCore.Design/Design/Internal/MigrationsOperations.cs @@ -217,6 +217,29 @@ public virtual void UpdateDatabase( string? connectionString, string? contextType) { + // Fix wildcard * issue #38254 + if (contextType == "*") + { + var contexts = _contextOperations.CreateAllContexts(); + foreach (var item in contexts) + { + using (item) + { + if (connectionString is not null) + item.Database.SetConnectionString(connectionString); + + var services = _servicesBuilder.Build(item); + EnsureServices(services); + + var migrator = services.GetRequiredService(); + migrator.Migrate(targetMigration); + } + } + + _reporter.WriteInformation(DesignStrings.Done); + return; + } + using (var context = _contextOperations.CreateContext(contextType)) { if (connectionString != null) diff --git a/test/EFCore.Design.Tests/Design/Internal/MigrationsOperationsTest.cs b/test/EFCore.Design.Tests/Design/Internal/MigrationsOperationsTest.cs index 80ac8f71775..1ea6030627c 100644 --- a/test/EFCore.Design.Tests/Design/Internal/MigrationsOperationsTest.cs +++ b/test/EFCore.Design.Tests/Design/Internal/MigrationsOperationsTest.cs @@ -85,6 +85,23 @@ public void AddMigration_throws_when_name_is_whitespace() Assert.Equal(DesignStrings.MigrationNameRequired, exception.Message); } + [ConditionalFact] + public void UpdateDatabase_with_wildcard_context_runs_for_all_contexts() + { + var assembly = MockAssembly.Create([typeof(AssemblyTestContext), typeof(TestContext)]); + var operations = new TestMigrationsOperations( + new TestOperationReporter(), + assembly, + assembly, + "projectDir", + "RootNamespace", + "C#", + nullable: false, + args: []); + + operations.UpdateDatabase(null, null, "*"); + } + private class TestContext : DbContext; private class AssemblyTestContext : DbContext From d765a84f359af15f638330b7cab863eafa86cff5 Mon Sep 17 00:00:00 2001 From: Bruno Ferreira Date: Wed, 13 May 2026 21:58:10 -0300 Subject: [PATCH 2/7] fix: throw when no contexts found with wildcard, add test --- .../Design/Internal/MigrationsOperations.cs | 12 ++++++++++-- .../Design/Internal/MigrationsOperationsTest.cs | 5 ++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/EFCore.Design/Design/Internal/MigrationsOperations.cs b/src/EFCore.Design/Design/Internal/MigrationsOperations.cs index 93ffc6ec61f..e97db0e2b00 100644 --- a/src/EFCore.Design/Design/Internal/MigrationsOperations.cs +++ b/src/EFCore.Design/Design/Internal/MigrationsOperations.cs @@ -221,12 +221,20 @@ public virtual void UpdateDatabase( if (contextType == "*") { var contexts = _contextOperations.CreateAllContexts(); + + if (!contexts.Any()) + { + throw new OperationException(DesignStrings.NoContext(_assembly.GetName().Name)); + } + foreach (var item in contexts) { using (item) { if (connectionString is not null) - item.Database.SetConnectionString(connectionString); + { + item.Database.SetConnectionString(connectionString); + } var services = _servicesBuilder.Build(item); EnsureServices(services); @@ -242,7 +250,7 @@ public virtual void UpdateDatabase( using (var context = _contextOperations.CreateContext(contextType)) { - if (connectionString != null) + if (connectionString is not null) { context.Database.SetConnectionString(connectionString); } diff --git a/test/EFCore.Design.Tests/Design/Internal/MigrationsOperationsTest.cs b/test/EFCore.Design.Tests/Design/Internal/MigrationsOperationsTest.cs index 1ea6030627c..747166117a4 100644 --- a/test/EFCore.Design.Tests/Design/Internal/MigrationsOperationsTest.cs +++ b/test/EFCore.Design.Tests/Design/Internal/MigrationsOperationsTest.cs @@ -89,8 +89,9 @@ public void AddMigration_throws_when_name_is_whitespace() public void UpdateDatabase_with_wildcard_context_runs_for_all_contexts() { var assembly = MockAssembly.Create([typeof(AssemblyTestContext), typeof(TestContext)]); + var reporter = new TestOperationReporter(); var operations = new TestMigrationsOperations( - new TestOperationReporter(), + reporter, assembly, assembly, "projectDir", @@ -100,6 +101,8 @@ public void UpdateDatabase_with_wildcard_context_runs_for_all_contexts() args: []); operations.UpdateDatabase(null, null, "*"); + + Assert.Contains(reporter.Messages, m => m.Contains(DesignStrings.Done)); } private class TestContext : DbContext; From e5c92fc6f768cd22650e54898b3464faee719494 Mon Sep 17 00:00:00 2001 From: Bruno Ferreira Date: Thu, 14 May 2026 22:49:07 -0300 Subject: [PATCH 3/7] fix: handle wildcard '*' in --context parameter for UpdateDatabase - Implement wildcard support in UpdateDatabase method - Throw OperationException when no contexts found (consistency with non-wildcard path) - MigrationsBundle covered by this fix (calls UpdateDatabase internally) - Remove weak test coverage (no existing tests for UpdateDatabase in codebase) --- .../Design/Internal/MigrationsOperations.cs | 22 +++++++++---------- .../Internal/MigrationsOperationsTest.cs | 20 ----------------- 2 files changed, 11 insertions(+), 31 deletions(-) diff --git a/src/EFCore.Design/Design/Internal/MigrationsOperations.cs b/src/EFCore.Design/Design/Internal/MigrationsOperations.cs index e97db0e2b00..4feafe5b91b 100644 --- a/src/EFCore.Design/Design/Internal/MigrationsOperations.cs +++ b/src/EFCore.Design/Design/Internal/MigrationsOperations.cs @@ -227,22 +227,22 @@ public virtual void UpdateDatabase( throw new OperationException(DesignStrings.NoContext(_assembly.GetName().Name)); } - foreach (var item in contexts) + foreach (var item in contexts) + { + using (item) { - using (item) + if (connectionString is not null) { - if (connectionString is not null) - { - item.Database.SetConnectionString(connectionString); - } + item.Database.SetConnectionString(connectionString); + } - var services = _servicesBuilder.Build(item); - EnsureServices(services); + var services = _servicesBuilder.Build(item); + EnsureServices(services); - var migrator = services.GetRequiredService(); - migrator.Migrate(targetMigration); - } + var migrator = services.GetRequiredService(); + migrator.Migrate(targetMigration); } + } _reporter.WriteInformation(DesignStrings.Done); return; diff --git a/test/EFCore.Design.Tests/Design/Internal/MigrationsOperationsTest.cs b/test/EFCore.Design.Tests/Design/Internal/MigrationsOperationsTest.cs index 747166117a4..80ac8f71775 100644 --- a/test/EFCore.Design.Tests/Design/Internal/MigrationsOperationsTest.cs +++ b/test/EFCore.Design.Tests/Design/Internal/MigrationsOperationsTest.cs @@ -85,26 +85,6 @@ public void AddMigration_throws_when_name_is_whitespace() Assert.Equal(DesignStrings.MigrationNameRequired, exception.Message); } - [ConditionalFact] - public void UpdateDatabase_with_wildcard_context_runs_for_all_contexts() - { - var assembly = MockAssembly.Create([typeof(AssemblyTestContext), typeof(TestContext)]); - var reporter = new TestOperationReporter(); - var operations = new TestMigrationsOperations( - reporter, - assembly, - assembly, - "projectDir", - "RootNamespace", - "C#", - nullable: false, - args: []); - - operations.UpdateDatabase(null, null, "*"); - - Assert.Contains(reporter.Messages, m => m.Contains(DesignStrings.Done)); - } - private class TestContext : DbContext; private class AssemblyTestContext : DbContext From 4803e2de314b13423cdfda029cf1fb1b2e2c3ab2 Mon Sep 17 00:00:00 2001 From: Bruno Ferreira Date: Fri, 15 May 2026 18:56:50 -0300 Subject: [PATCH 4/7] Throw OperationException when wildcard '*' is used with unsupported commands --- .../Design/Internal/DbContextOperations.cs | 10 ++++++++++ .../Design/Internal/MigrationsOperations.cs | 20 +++++++++++++++++++ .../Properties/DesignStrings.Designer.cs | 6 ++++++ .../Properties/DesignStrings.resx | 3 +++ 4 files changed, 39 insertions(+) diff --git a/src/EFCore.Design/Design/Internal/DbContextOperations.cs b/src/EFCore.Design/Design/Internal/DbContextOperations.cs index 78a3bcb808d..11997ee8200 100644 --- a/src/EFCore.Design/Design/Internal/DbContextOperations.cs +++ b/src/EFCore.Design/Design/Internal/DbContextOperations.cs @@ -102,6 +102,11 @@ protected DbContextOperations( /// public virtual void DropDatabase(string? contextType, string? connectionString) { + if (contextType == "*") + { + throw new OperationException(DesignStrings.WildcardNotSupported); + } + using var context = CreateContext(contextType); if (connectionString != null) @@ -425,6 +430,11 @@ private IReadOnlyList PrecompileQueries( /// public virtual ContextInfo GetContextInfo(string? contextType, string? connectionString = null) { + if (contextType == "*") + { + throw new OperationException(DesignStrings.WildcardNotSupported); + } + using var context = CreateContext(contextType); if (connectionString != null) diff --git a/src/EFCore.Design/Design/Internal/MigrationsOperations.cs b/src/EFCore.Design/Design/Internal/MigrationsOperations.cs index 4feafe5b91b..3fe25709ad4 100644 --- a/src/EFCore.Design/Design/Internal/MigrationsOperations.cs +++ b/src/EFCore.Design/Design/Internal/MigrationsOperations.cs @@ -73,6 +73,11 @@ public virtual MigrationFiles AddMigration( string? @namespace, bool dryRun) { + if (contextType == "*") + { + throw new OperationException(DesignStrings.WildcardNotSupported); + } + using var context = _contextOperations.CreateContext(contextType); var services = PrepareForMigration(name, context); @@ -147,6 +152,11 @@ public virtual IEnumerable GetMigrations( string? connectionString, bool noConnect) { + if (contextType == "*") + { + throw new OperationException(DesignStrings.WildcardNotSupported); + } + using var context = _contextOperations.CreateContext(contextType); if (connectionString != null) @@ -197,6 +207,11 @@ public virtual string ScriptMigration( MigrationsSqlGenerationOptions options, string? contextType) { + if (contextType == "*") + { + throw new OperationException(DesignStrings.WildcardNotSupported); + } + using var context = _contextOperations.CreateContext(contextType); var services = _servicesBuilder.Build(context); EnsureServices(services); @@ -278,6 +293,11 @@ public virtual MigrationFiles RemoveMigration( bool dryRun, string? connectionString) { + if (contextType == "*") + { + throw new OperationException(DesignStrings.WildcardNotSupported); + } + using var context = _contextOperations.CreateContext(contextType); if (connectionString != null) diff --git a/src/EFCore.Design/Properties/DesignStrings.Designer.cs b/src/EFCore.Design/Properties/DesignStrings.Designer.cs index 140351da3f2..caaac6bc315 100644 --- a/src/EFCore.Design/Properties/DesignStrings.Designer.cs +++ b/src/EFCore.Design/Properties/DesignStrings.Designer.cs @@ -979,6 +979,12 @@ public static string MigrationCreatedAndApplied(object? migrationId) GetString("MigrationCreatedAndApplied", nameof(migrationId)), migrationId); + /// + /// The wildcard '*' is not supported for this command. + /// + public static string WildcardNotSupported + => GetString("WildcardNotSupported"); + private static string GetString(string name, params string[] formatterNames) { var value = _resourceManager.GetString(name)!; diff --git a/src/EFCore.Design/Properties/DesignStrings.resx b/src/EFCore.Design/Properties/DesignStrings.resx index f167b4fb0da..b3da82b6d41 100644 --- a/src/EFCore.Design/Properties/DesignStrings.resx +++ b/src/EFCore.Design/Properties/DesignStrings.resx @@ -512,4 +512,7 @@ Change your target project to the migrations project by using the Package Manage Migration '{migrationId}' was successfully created and applied. + + The wildcard '*' is not supported for this command. + \ No newline at end of file From 66366b4ffb7b85394cefbc5f05298c528bbf0809 Mon Sep 17 00:00:00 2001 From: Bruno Ferreira Date: Fri, 15 May 2026 19:07:33 -0300 Subject: [PATCH 5/7] Extract migration logic into MigrateContext to avoid duplication --- .../Design/Internal/MigrationsOperations.cs | 40 +++++++++---------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/src/EFCore.Design/Design/Internal/MigrationsOperations.cs b/src/EFCore.Design/Design/Internal/MigrationsOperations.cs index 3fe25709ad4..bc41515df9e 100644 --- a/src/EFCore.Design/Design/Internal/MigrationsOperations.cs +++ b/src/EFCore.Design/Design/Internal/MigrationsOperations.cs @@ -228,9 +228,9 @@ public virtual string ScriptMigration( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual void UpdateDatabase( - string? targetMigration, - string? connectionString, - string? contextType) + string? targetMigration, + string? connectionString, + string? contextType) { // Fix wildcard * issue #38254 if (contextType == "*") @@ -246,16 +246,7 @@ public virtual void UpdateDatabase( { using (item) { - if (connectionString is not null) - { - item.Database.SetConnectionString(connectionString); - } - - var services = _servicesBuilder.Build(item); - EnsureServices(services); - - var migrator = services.GetRequiredService(); - migrator.Migrate(targetMigration); + MigrateContext(item, targetMigration, connectionString); } } @@ -265,19 +256,24 @@ public virtual void UpdateDatabase( using (var context = _contextOperations.CreateContext(contextType)) { - if (connectionString is not null) - { - context.Database.SetConnectionString(connectionString); - } + MigrateContext(context, targetMigration, connectionString); + } - var services = _servicesBuilder.Build(context); - EnsureServices(services); + _reporter.WriteInformation(DesignStrings.Done); + } - var migrator = services.GetRequiredService(); - migrator.Migrate(targetMigration); + private void MigrateContext(DbContext context, string? targetMigration, string? connectionString) + { + if (connectionString is not null) + { + context.Database.SetConnectionString(connectionString); } - _reporter.WriteInformation(DesignStrings.Done); + var services = _servicesBuilder.Build(context); + EnsureServices(services); + + var migrator = services.GetRequiredService(); + migrator.Migrate(targetMigration); } /// From fa569a10d47e715caafbb46dac8be9ef5ed1bce3 Mon Sep 17 00:00:00 2001 From: Bruno Ferreira Date: Fri, 15 May 2026 19:08:42 -0300 Subject: [PATCH 6/7] remove comment --- src/EFCore.Design/Design/Internal/MigrationsOperations.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/EFCore.Design/Design/Internal/MigrationsOperations.cs b/src/EFCore.Design/Design/Internal/MigrationsOperations.cs index bc41515df9e..a273f31d14e 100644 --- a/src/EFCore.Design/Design/Internal/MigrationsOperations.cs +++ b/src/EFCore.Design/Design/Internal/MigrationsOperations.cs @@ -232,7 +232,6 @@ public virtual void UpdateDatabase( string? connectionString, string? contextType) { - // Fix wildcard * issue #38254 if (contextType == "*") { var contexts = _contextOperations.CreateAllContexts(); From 79ed2a95142c35a2ac920625720b1813d5249db8 Mon Sep 17 00:00:00 2001 From: Bruno Ferreira Date: Fri, 15 May 2026 20:04:31 -0300 Subject: [PATCH 7/7] Add wildcard check to MigrationsBundleCommand --- src/EFCore.Design/Design/Internal/MigrationsOperations.cs | 6 +++--- src/EFCore.Design/Properties/DesignStrings.resx | 2 +- src/ef/Commands/MigrationsBundleCommand.cs | 5 +++++ src/ef/Properties/Resources.Designer.cs | 6 ++++++ src/ef/Properties/Resources.resx | 3 +++ 5 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/EFCore.Design/Design/Internal/MigrationsOperations.cs b/src/EFCore.Design/Design/Internal/MigrationsOperations.cs index a273f31d14e..db89d8a69e9 100644 --- a/src/EFCore.Design/Design/Internal/MigrationsOperations.cs +++ b/src/EFCore.Design/Design/Internal/MigrationsOperations.cs @@ -228,9 +228,9 @@ public virtual string ScriptMigration( /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public virtual void UpdateDatabase( - string? targetMigration, - string? connectionString, - string? contextType) + string? targetMigration, + string? connectionString, + string? contextType) { if (contextType == "*") { diff --git a/src/EFCore.Design/Properties/DesignStrings.resx b/src/EFCore.Design/Properties/DesignStrings.resx index b3da82b6d41..3ce3000d05f 100644 --- a/src/EFCore.Design/Properties/DesignStrings.resx +++ b/src/EFCore.Design/Properties/DesignStrings.resx @@ -513,6 +513,6 @@ Change your target project to the migrations project by using the Package Manage Migration '{migrationId}' was successfully created and applied. - The wildcard '*' is not supported for this command. + The wildcard '*' can only be used with commands that run for all contexts found. Specify a context name for this command. \ No newline at end of file diff --git a/src/ef/Commands/MigrationsBundleCommand.cs b/src/ef/Commands/MigrationsBundleCommand.cs index 6f69298b11c..4961fed1bff 100644 --- a/src/ef/Commands/MigrationsBundleCommand.cs +++ b/src/ef/Commands/MigrationsBundleCommand.cs @@ -41,6 +41,11 @@ protected override int Execute(string[] args) throw new CommandException(Resources.VersionRequired("6.0.0")); } + if (Context!.Value() == "*") + { + throw new CommandException(Resources.WildcardNotSupported); + } + context = (string)executor.GetContextInfo(Context!.Value())["Type"]!; } diff --git a/src/ef/Properties/Resources.Designer.cs b/src/ef/Properties/Resources.Designer.cs index 50a5257a3af..2cf6e3d7fb0 100644 --- a/src/ef/Properties/Resources.Designer.cs +++ b/src/ef/Properties/Resources.Designer.cs @@ -725,6 +725,12 @@ public static string WritingFile(object? file) GetString("WritingFile", nameof(file)), file); + /// + /// The wildcard '*' is not supported for this command. + /// + public static string WildcardNotSupported + => GetString("WildcardNotSupported"); + private static string GetString(string name, params string[] formatterNames) { var value = _resourceManager.GetString(name)!; diff --git a/src/ef/Properties/Resources.resx b/src/ef/Properties/Resources.resx index 86f219db094..eddeede5702 100644 --- a/src/ef/Properties/Resources.resx +++ b/src/ef/Properties/Resources.resx @@ -441,4 +441,7 @@ Writing '{file}'... + + The wildcard '*' is not supported for this command. +