From c51694360b17574f755bc756b8fd33de5827d934 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Mar 2026 05:44:45 +0000 Subject: [PATCH 1/7] Initial plan From 7bcbeb7ade08ba956b32a967ebb88c7cb3948fbc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Mar 2026 05:50:22 +0000 Subject: [PATCH 2/7] Show a warning when dotnet-ef tools are used with a platform-specific app Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- src/EFCore.Tools/tools/EntityFrameworkCore.psm1 | 6 ++++++ src/dotnet-ef/RootCommand.cs | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/src/EFCore.Tools/tools/EntityFrameworkCore.psm1 b/src/EFCore.Tools/tools/EntityFrameworkCore.psm1 index 09ec3ae237e..8bf833cdb97 100644 --- a/src/EFCore.Tools/tools/EntityFrameworkCore.psm1 +++ b/src/EFCore.Tools/tools/EntityFrameworkCore.psm1 @@ -1298,6 +1298,12 @@ function EF($project, $startupProject, $params, $applicationArgs, [switch] $skip 'Core Package Manager Console Tools don''t support this platform. See https://aka.ms/efcore-docs-pmc-tfms for more ' + 'information.' } + if ($targetPlatformIdentifier) + { + Write-Warning "Startup project '$($startupProject.ProjectName)' targets platform '$targetPlatformIdentifier'. The Entity " + + 'Framework Core Package Manager Console Tools don''t support this platform. See https://aka.ms/efcore-docs-pmc-tfms ' + + 'for more information.' + } $exePath = (Get-Command 'dotnet').Path diff --git a/src/dotnet-ef/RootCommand.cs b/src/dotnet-ef/RootCommand.cs index fa70430b979..ea3135f5870 100644 --- a/src/dotnet-ef/RootCommand.cs +++ b/src/dotnet-ef/RootCommand.cs @@ -106,6 +106,12 @@ protected override int Execute(string[] _) startupProject.AssemblyName + ".runtimeconfig.json"); var projectAssetsFile = startupProject.ProjectAssetsFile; + if (!string.IsNullOrEmpty(startupProject.TargetPlatformIdentifier)) + { + Reporter.WriteWarning( + Resources.UnsupportedPlatform(startupProject.ProjectName, startupProject.TargetPlatformIdentifier)); + } + var targetFramework = new FrameworkName(startupProject.TargetFrameworkMoniker!); if (targetFramework.Identifier == ".NETFramework") { From e60ab2134894efa2392b1705a40a0a15830544ec Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Mar 2026 19:44:51 +0000 Subject: [PATCH 3/7] Only warn when TargetPlatformIdentifier differs from the current execution platform Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- src/EFCore.Tools/tools/EntityFrameworkCore.psm1 | 6 ------ src/dotnet-ef/RootCommand.cs | 11 ++++++++++- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/EFCore.Tools/tools/EntityFrameworkCore.psm1 b/src/EFCore.Tools/tools/EntityFrameworkCore.psm1 index 8bf833cdb97..09ec3ae237e 100644 --- a/src/EFCore.Tools/tools/EntityFrameworkCore.psm1 +++ b/src/EFCore.Tools/tools/EntityFrameworkCore.psm1 @@ -1298,12 +1298,6 @@ function EF($project, $startupProject, $params, $applicationArgs, [switch] $skip 'Core Package Manager Console Tools don''t support this platform. See https://aka.ms/efcore-docs-pmc-tfms for more ' + 'information.' } - if ($targetPlatformIdentifier) - { - Write-Warning "Startup project '$($startupProject.ProjectName)' targets platform '$targetPlatformIdentifier'. The Entity " + - 'Framework Core Package Manager Console Tools don''t support this platform. See https://aka.ms/efcore-docs-pmc-tfms ' + - 'for more information.' - } $exePath = (Get-Command 'dotnet').Path diff --git a/src/dotnet-ef/RootCommand.cs b/src/dotnet-ef/RootCommand.cs index ea3135f5870..1f3e35a3b6b 100644 --- a/src/dotnet-ef/RootCommand.cs +++ b/src/dotnet-ef/RootCommand.cs @@ -106,7 +106,8 @@ protected override int Execute(string[] _) startupProject.AssemblyName + ".runtimeconfig.json"); var projectAssetsFile = startupProject.ProjectAssetsFile; - if (!string.IsNullOrEmpty(startupProject.TargetPlatformIdentifier)) + if (!string.IsNullOrEmpty(startupProject.TargetPlatformIdentifier) + && !IsCurrentPlatform(startupProject.TargetPlatformIdentifier)) { Reporter.WriteWarning( Resources.UnsupportedPlatform(startupProject.ProjectName, startupProject.TargetPlatformIdentifier)); @@ -319,6 +320,14 @@ private static string GetVersion() => typeof(RootCommand).Assembly.GetCustomAttribute()! .InformationalVersion; + private static bool IsCurrentPlatform(string targetPlatformIdentifier) + => string.Equals(targetPlatformIdentifier, "Windows", StringComparison.OrdinalIgnoreCase) + ? OperatingSystem.IsWindows() + : string.Equals(targetPlatformIdentifier, "Linux", StringComparison.OrdinalIgnoreCase) + ? OperatingSystem.IsLinux() + : string.Equals(targetPlatformIdentifier, "macOS", StringComparison.OrdinalIgnoreCase) + && OperatingSystem.IsMacOS(); + private static bool ShouldHelp(IReadOnlyList commands, IList args) => args.Count == 0 || commands.Count == 0 From 950dd960245db5a27bc88209382fac5e91a7079c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Mar 2026 20:40:24 +0000 Subject: [PATCH 4/7] Refactor: extract GetTargetPlatformIdentifier and move logic into IsCurrentPlatform Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- src/dotnet-ef/RootCommand.cs | 40 ++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/src/dotnet-ef/RootCommand.cs b/src/dotnet-ef/RootCommand.cs index 1f3e35a3b6b..9b02690bae6 100644 --- a/src/dotnet-ef/RootCommand.cs +++ b/src/dotnet-ef/RootCommand.cs @@ -106,8 +106,7 @@ protected override int Execute(string[] _) startupProject.AssemblyName + ".runtimeconfig.json"); var projectAssetsFile = startupProject.ProjectAssetsFile; - if (!string.IsNullOrEmpty(startupProject.TargetPlatformIdentifier) - && !IsCurrentPlatform(startupProject.TargetPlatformIdentifier)) + if (!IsCurrentPlatform(startupProject.TargetPlatformIdentifier)) { Reporter.WriteWarning( Resources.UnsupportedPlatform(startupProject.ProjectName, startupProject.TargetPlatformIdentifier)); @@ -320,13 +319,36 @@ private static string GetVersion() => typeof(RootCommand).Assembly.GetCustomAttribute()! .InformationalVersion; - private static bool IsCurrentPlatform(string targetPlatformIdentifier) - => string.Equals(targetPlatformIdentifier, "Windows", StringComparison.OrdinalIgnoreCase) - ? OperatingSystem.IsWindows() - : string.Equals(targetPlatformIdentifier, "Linux", StringComparison.OrdinalIgnoreCase) - ? OperatingSystem.IsLinux() - : string.Equals(targetPlatformIdentifier, "macOS", StringComparison.OrdinalIgnoreCase) - && OperatingSystem.IsMacOS(); + private static bool IsCurrentPlatform(string? targetPlatformIdentifier) + { + if (string.IsNullOrEmpty(targetPlatformIdentifier)) + { + return true; + } + + var currentPlatformIdentifier = GetTargetPlatformIdentifier(); + return string.Equals(targetPlatformIdentifier, currentPlatformIdentifier, StringComparison.OrdinalIgnoreCase); + } + + private static string? GetTargetPlatformIdentifier() + { + if (OperatingSystem.IsWindows()) + { + return "Windows"; + } + + if (OperatingSystem.IsLinux()) + { + return "Linux"; + } + + if (OperatingSystem.IsMacOS()) + { + return "macOS"; + } + + return null; + } private static bool ShouldHelp(IReadOnlyList commands, IList args) => args.Count == 0 From 20a9f795e21a1b812407048648695347cc1082a9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Mar 2026 20:52:02 +0000 Subject: [PATCH 5/7] Use MSBuild-style GetTargetPlatformIdentifier to extract platform from TargetFramework Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- src/dotnet-ef/RootCommand.cs | 43 ++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/src/dotnet-ef/RootCommand.cs b/src/dotnet-ef/RootCommand.cs index 9b02690bae6..d5ce6385917 100644 --- a/src/dotnet-ef/RootCommand.cs +++ b/src/dotnet-ef/RootCommand.cs @@ -106,10 +106,11 @@ protected override int Execute(string[] _) startupProject.AssemblyName + ".runtimeconfig.json"); var projectAssetsFile = startupProject.ProjectAssetsFile; - if (!IsCurrentPlatform(startupProject.TargetPlatformIdentifier)) + var targetPlatformIdentifier = GetTargetPlatformIdentifier(startupProject.TargetFramework); + if (!IsCurrentPlatform(targetPlatformIdentifier)) { Reporter.WriteWarning( - Resources.UnsupportedPlatform(startupProject.ProjectName, startupProject.TargetPlatformIdentifier)); + Resources.UnsupportedPlatform(startupProject.ProjectName, targetPlatformIdentifier)); } var targetFramework = new FrameworkName(startupProject.TargetFrameworkMoniker!); @@ -326,28 +327,46 @@ private static bool IsCurrentPlatform(string? targetPlatformIdentifier) return true; } - var currentPlatformIdentifier = GetTargetPlatformIdentifier(); - return string.Equals(targetPlatformIdentifier, currentPlatformIdentifier, StringComparison.OrdinalIgnoreCase); + if (string.Equals(targetPlatformIdentifier, "windows", StringComparison.OrdinalIgnoreCase)) + { + return OperatingSystem.IsWindows(); + } + + if (string.Equals(targetPlatformIdentifier, "linux", StringComparison.OrdinalIgnoreCase)) + { + return OperatingSystem.IsLinux(); + } + + if (string.Equals(targetPlatformIdentifier, "osx", StringComparison.OrdinalIgnoreCase) + || string.Equals(targetPlatformIdentifier, "macos", StringComparison.OrdinalIgnoreCase)) + { + return OperatingSystem.IsMacOS(); + } + + return false; } - private static string? GetTargetPlatformIdentifier() + private static string? GetTargetPlatformIdentifier(string? targetFramework) { - if (OperatingSystem.IsWindows()) + if (string.IsNullOrEmpty(targetFramework)) { - return "Windows"; + return null; } - if (OperatingSystem.IsLinux()) + var dashIndex = targetFramework.IndexOf('-'); + if (dashIndex < 0 || dashIndex >= targetFramework.Length - 1) { - return "Linux"; + return null; } - if (OperatingSystem.IsMacOS()) + var platformAndVersion = targetFramework[(dashIndex + 1)..]; + var i = 0; + while (i < platformAndVersion.Length && !char.IsDigit(platformAndVersion[i])) { - return "macOS"; + i++; } - return null; + return i > 0 ? platformAndVersion[..i] : null; } private static bool ShouldHelp(IReadOnlyList commands, IList args) From 81db7e80cba3ba68b1391340cb8b466bacd6b54e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 25 Mar 2026 00:19:08 +0000 Subject: [PATCH 6/7] Always warn for platform-specific projects; new PlatformSpecificProject message with docs link and IDesignTimeDbContextFactory<> guidance Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> Agent-Logs-Url: https://github.com/dotnet/efcore/sessions/6e12c379-3c85-4c7e-a45c-5ed92f003975 --- .../Properties/Resources.Designer.cs | 8 +++ src/dotnet-ef/Properties/Resources.resx | 3 + src/dotnet-ef/RootCommand.cs | 55 ++++--------------- 3 files changed, 22 insertions(+), 44 deletions(-) diff --git a/src/dotnet-ef/Properties/Resources.Designer.cs b/src/dotnet-ef/Properties/Resources.Designer.cs index c722ed44878..75b9b5c17cd 100644 --- a/src/dotnet-ef/Properties/Resources.Designer.cs +++ b/src/dotnet-ef/Properties/Resources.Designer.cs @@ -459,6 +459,14 @@ public static string PrecompileQueriesDescription public static string PrecompileQueriesWarning => GetString("PrecompileQueriesWarning"); + /// + /// Startup project '{startupProject}' targets a platform-specific framework: '{targetFrameworkValue}'. The Entity Framework Core .NET Command-line Tools might not function correctly. Implement IDesignTimeDbContextFactory<> to ensure design-time tools work correctly with this project. See https://aka.ms/efcore-docs-migrations-projects for more information. + /// + public static string PlatformSpecificProject(object? startupProject, object? targetFrameworkValue) + => string.Format( + GetString("PlatformSpecificProject", nameof(startupProject), nameof(targetFrameworkValue)), + startupProject, targetFrameworkValue); + /// /// Prefix output with level. /// diff --git a/src/dotnet-ef/Properties/Resources.resx b/src/dotnet-ef/Properties/Resources.resx index 323919ca847..5788b6d0def 100644 --- a/src/dotnet-ef/Properties/Resources.resx +++ b/src/dotnet-ef/Properties/Resources.resx @@ -330,6 +330,9 @@ Query precompilation is an experimental feature and should be used with caution. + + Startup project '{startupProject}' targets a platform-specific framework: '{targetFrameworkValue}'. The Entity Framework Core .NET Command-line Tools might not function correctly. Implement IDesignTimeDbContextFactory<> to ensure design-time tools work correctly with this project. See https://aka.ms/efcore-docs-migrations-projects for more information. + Prefix output with level. diff --git a/src/dotnet-ef/RootCommand.cs b/src/dotnet-ef/RootCommand.cs index d5ce6385917..99ad3ed3b78 100644 --- a/src/dotnet-ef/RootCommand.cs +++ b/src/dotnet-ef/RootCommand.cs @@ -106,11 +106,15 @@ protected override int Execute(string[] _) startupProject.AssemblyName + ".runtimeconfig.json"); var projectAssetsFile = startupProject.ProjectAssetsFile; - var targetPlatformIdentifier = GetTargetPlatformIdentifier(startupProject.TargetFramework); - if (!IsCurrentPlatform(targetPlatformIdentifier)) + if (!string.IsNullOrEmpty(startupProject.TargetPlatformIdentifier)) { Reporter.WriteWarning( - Resources.UnsupportedPlatform(startupProject.ProjectName, targetPlatformIdentifier)); + Resources.PlatformSpecificProject(startupProject.ProjectName, startupProject.TargetPlatformIdentifier)); + } + else if (HasPlatformInTargetFramework(startupProject.TargetFramework)) + { + Reporter.WriteWarning( + Resources.PlatformSpecificProject(startupProject.ProjectName, startupProject.TargetFramework)); } var targetFramework = new FrameworkName(startupProject.TargetFrameworkMoniker!); @@ -320,53 +324,16 @@ private static string GetVersion() => typeof(RootCommand).Assembly.GetCustomAttribute()! .InformationalVersion; - private static bool IsCurrentPlatform(string? targetPlatformIdentifier) - { - if (string.IsNullOrEmpty(targetPlatformIdentifier)) - { - return true; - } - - if (string.Equals(targetPlatformIdentifier, "windows", StringComparison.OrdinalIgnoreCase)) - { - return OperatingSystem.IsWindows(); - } - - if (string.Equals(targetPlatformIdentifier, "linux", StringComparison.OrdinalIgnoreCase)) - { - return OperatingSystem.IsLinux(); - } - - if (string.Equals(targetPlatformIdentifier, "osx", StringComparison.OrdinalIgnoreCase) - || string.Equals(targetPlatformIdentifier, "macos", StringComparison.OrdinalIgnoreCase)) - { - return OperatingSystem.IsMacOS(); - } - - return false; - } - - private static string? GetTargetPlatformIdentifier(string? targetFramework) + private static bool HasPlatformInTargetFramework(string? targetFramework) { if (string.IsNullOrEmpty(targetFramework)) { - return null; + return false; } + // Check for netX.Y-Z form (e.g. net8.0-windows10.0.19041.0) var dashIndex = targetFramework.IndexOf('-'); - if (dashIndex < 0 || dashIndex >= targetFramework.Length - 1) - { - return null; - } - - var platformAndVersion = targetFramework[(dashIndex + 1)..]; - var i = 0; - while (i < platformAndVersion.Length && !char.IsDigit(platformAndVersion[i])) - { - i++; - } - - return i > 0 ? platformAndVersion[..i] : null; + return dashIndex > 0 && dashIndex < targetFramework.Length - 1; } private static bool ShouldHelp(IReadOnlyList commands, IList args) From bb702d48b0a57ca089e92e42e721a12d18265c1f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 25 Mar 2026 00:26:10 +0000 Subject: [PATCH 7/7] Simplify platform-specific warning to single if block, always use TargetFramework in message Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> Agent-Logs-Url: https://github.com/dotnet/efcore/sessions/aeeadad5-f2cb-43c0-bb20-80f4134a585d --- src/dotnet-ef/RootCommand.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/dotnet-ef/RootCommand.cs b/src/dotnet-ef/RootCommand.cs index 99ad3ed3b78..192fa7d3846 100644 --- a/src/dotnet-ef/RootCommand.cs +++ b/src/dotnet-ef/RootCommand.cs @@ -106,12 +106,8 @@ protected override int Execute(string[] _) startupProject.AssemblyName + ".runtimeconfig.json"); var projectAssetsFile = startupProject.ProjectAssetsFile; - if (!string.IsNullOrEmpty(startupProject.TargetPlatformIdentifier)) - { - Reporter.WriteWarning( - Resources.PlatformSpecificProject(startupProject.ProjectName, startupProject.TargetPlatformIdentifier)); - } - else if (HasPlatformInTargetFramework(startupProject.TargetFramework)) + if (!string.IsNullOrEmpty(startupProject.TargetPlatformIdentifier) + || HasPlatformInTargetFramework(startupProject.TargetFramework)) { Reporter.WriteWarning( Resources.PlatformSpecificProject(startupProject.ProjectName, startupProject.TargetFramework));