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 fa70430b979..192fa7d3846 100644
--- a/src/dotnet-ef/RootCommand.cs
+++ b/src/dotnet-ef/RootCommand.cs
@@ -106,6 +106,13 @@ protected override int Execute(string[] _)
startupProject.AssemblyName + ".runtimeconfig.json");
var projectAssetsFile = startupProject.ProjectAssetsFile;
+ if (!string.IsNullOrEmpty(startupProject.TargetPlatformIdentifier)
+ || HasPlatformInTargetFramework(startupProject.TargetFramework))
+ {
+ Reporter.WriteWarning(
+ Resources.PlatformSpecificProject(startupProject.ProjectName, startupProject.TargetFramework));
+ }
+
var targetFramework = new FrameworkName(startupProject.TargetFrameworkMoniker!);
if (targetFramework.Identifier == ".NETFramework")
{
@@ -313,6 +320,18 @@ private static string GetVersion()
=> typeof(RootCommand).Assembly.GetCustomAttribute()!
.InformationalVersion;
+ private static bool HasPlatformInTargetFramework(string? targetFramework)
+ {
+ if (string.IsNullOrEmpty(targetFramework))
+ {
+ return false;
+ }
+
+ // Check for netX.Y-Z form (e.g. net8.0-windows10.0.19041.0)
+ var dashIndex = targetFramework.IndexOf('-');
+ return dashIndex > 0 && dashIndex < targetFramework.Length - 1;
+ }
+
private static bool ShouldHelp(IReadOnlyList commands, IList args)
=> args.Count == 0
|| commands.Count == 0