diff --git a/Directory.Packages.props b/Directory.Packages.props
index 13682a1ed8a..b5b30003d44 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -53,8 +53,8 @@
-
-
-
+
+
+
\ No newline at end of file
diff --git a/eng/Versions.props b/eng/Versions.props
index 19609d973d6..5a713f0b8bb 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -2,9 +2,9 @@
10.0.1
- servicing
+ servicing
- False
+ False
true
- 17.14.28
- 17.14.28
- 17.14.28
- 4.14.0
- 4.14.0
- 4.14.0
-
-
17.15.0
17.15.0
17.15.0
5.0.0
5.0.0
5.0.0
- -->
-
- 1.1.3-beta1.24423.1
- 1.1.3-beta1.24352.1
- 1.14.2
- 1.3.2
- 1.12.0
- 2.1.11
diff --git a/src/EFCore.Design/EFCore.Design.csproj b/src/EFCore.Design/EFCore.Design.csproj
index f40ebae32f8..981497651ac 100644
--- a/src/EFCore.Design/EFCore.Design.csproj
+++ b/src/EFCore.Design/EFCore.Design.csproj
@@ -58,7 +58,7 @@
-
+
diff --git a/src/EFCore.Tasks/Tasks/Internal/OperationTaskBase.cs b/src/EFCore.Tasks/Tasks/Internal/OperationTaskBase.cs
index 830d4ca98e6..4e10cd493c0 100644
--- a/src/EFCore.Tasks/Tasks/Internal/OperationTaskBase.cs
+++ b/src/EFCore.Tasks/Tasks/Internal/OperationTaskBase.cs
@@ -81,6 +81,11 @@ public abstract class OperationTaskBase : ToolTask
///
public bool Nullable { get; set; }
+ ///
+ /// Runtime copy local items for dependency resolution.
+ ///
+ public ITaskItem[]? RuntimeCopyLocalItems { get; set; }
+
///
/// The additional arguments to pass to the dotnet-ef command.
///
diff --git a/src/EFCore.Tasks/Tasks/OptimizeDbContext.cs b/src/EFCore.Tasks/Tasks/OptimizeDbContext.cs
index 05ffa8615c8..aec1e5f8e02 100644
--- a/src/EFCore.Tasks/Tasks/OptimizeDbContext.cs
+++ b/src/EFCore.Tasks/Tasks/OptimizeDbContext.cs
@@ -80,6 +80,8 @@ public override bool Execute()
if (PrecompileQueries)
{
AdditionalArguments.Add("--precompile-queries");
+
+ CopyBuildHost();
}
AdditionalArguments.Add("--nativeaot");
@@ -106,4 +108,48 @@ public override bool Execute()
return !Log.HasLoggedErrors;
}
+
+ private void CopyBuildHost()
+ {
+ var msbuildWorkspacesItem = RuntimeCopyLocalItems?.FirstOrDefault(item =>
+ string.Equals(item.GetMetadata("Filename"), "Microsoft.CodeAnalysis.Workspaces.MSBuild", StringComparison.OrdinalIgnoreCase));
+ if (msbuildWorkspacesItem == null
+ || !string.Equals(msbuildWorkspacesItem.GetMetadata("CopyLocal"), "true", StringComparison.OrdinalIgnoreCase)
+ || msbuildWorkspacesItem.GetMetadata("FullPath") is not { } fullPath
+ || string.IsNullOrEmpty(fullPath)
+ || Path.GetDirectoryName(fullPath) is not { } itemDirectory
+ || string.IsNullOrEmpty(itemDirectory))
+ {
+ return;
+ }
+
+ var contentFilesPath = Path.GetFullPath(Path.Combine(itemDirectory, "..", "..", "contentFiles", "any", "any"));
+ var targetDir = Path.GetDirectoryName(Path.GetFullPath(Assembly.ItemSpec))!;
+
+ CopyDirectoryRecursive(contentFilesPath, targetDir);
+ }
+
+ private static void CopyDirectoryRecursive(string sourceDir, string targetDir)
+ {
+ var directory = new DirectoryInfo(sourceDir);
+ if (!directory.Exists)
+ {
+ return;
+ }
+
+ Directory.CreateDirectory(targetDir);
+ foreach (var file in directory.GetFiles())
+ {
+ var filePath = Path.Combine(targetDir, file.Name);
+ if (!File.Exists(filePath))
+ {
+ file.CopyTo(filePath, overwrite: false);
+ }
+ }
+
+ foreach (var subDir in directory.GetDirectories())
+ {
+ CopyDirectoryRecursive(subDir.FullName, Path.Combine(targetDir, subDir.Name));
+ }
+ }
}
diff --git a/src/EFCore.Tasks/buildTransitive/Microsoft.EntityFrameworkCore.Tasks.targets b/src/EFCore.Tasks/buildTransitive/Microsoft.EntityFrameworkCore.Tasks.targets
index 31e0dbe20a3..1032f4edbea 100644
--- a/src/EFCore.Tasks/buildTransitive/Microsoft.EntityFrameworkCore.Tasks.targets
+++ b/src/EFCore.Tasks/buildTransitive/Microsoft.EntityFrameworkCore.Tasks.targets
@@ -106,6 +106,7 @@ For Publish:
TargetNamespace="$(EFTargetNamespace)"
Language="$(Language)"
Nullable="$(EFNullable)"
+ RuntimeCopyLocalItems="@(RuntimeCopyLocalItems)"
OutputDir="$(EFOutputDir)"
Project="$(MSBuildProjectFullPath)"
ProjectDir="$(MSBuildProjectDirectory)"
diff --git a/src/EFCore.Tools/tools/EntityFrameworkCore.psm1 b/src/EFCore.Tools/tools/EntityFrameworkCore.psm1
index ce63472efc5..f236877f45c 100644
--- a/src/EFCore.Tools/tools/EntityFrameworkCore.psm1
+++ b/src/EFCore.Tools/tools/EntityFrameworkCore.psm1
@@ -1338,6 +1338,24 @@ function EF($project, $startupProject, $params, $applicationArgs, [switch] $skip
$params += '--design-assembly', $designReference.FullPath
}
+ $msbuildWorkspacesItem = $references.Items.RuntimeCopyLocalItems | ? {
+ $_.Filename -eq 'Microsoft.CodeAnalysis.Workspaces.MSBuild'
+ } | Select-Object -First 1
+
+ if ($msbuildWorkspacesItem -ne $null -and $msbuildWorkspacesItem.CopyLocal -eq 'true')
+ {
+ $itemDirectory = [IO.Path]::GetDirectoryName($msbuildWorkspacesItem.FullPath)
+ if ($itemDirectory)
+ {
+ $contentFilesPath = [IO.Path]::GetFullPath([IO.Path]::Combine($itemDirectory, '..', '..', 'contentFiles', 'any', 'any'))
+
+ if ([IO.Directory]::Exists($contentFilesPath))
+ {
+ Copy-Item "$contentFilesPath\*" $targetDir -Recurse -ErrorAction SilentlyContinue
+ }
+ }
+ }
+
$arguments = ToArguments $params
if ($applicationArgs)
{
diff --git a/src/dotnet-ef/Project.cs b/src/dotnet-ef/Project.cs
index 68e0203665e..578550045ce 100644
--- a/src/dotnet-ef/Project.cs
+++ b/src/dotnet-ef/Project.cs
@@ -90,11 +90,16 @@ public static Project FromFile(
var metadata = JsonSerializer.Deserialize(output.ToString())!;
- var designAssembly = metadata.Items["RuntimeCopyLocalItems"]
+ var runtimeCopyLocalItems = metadata.Items["RuntimeCopyLocalItems"];
+
+ var designAssembly = runtimeCopyLocalItems
.Select(i => i["FullPath"])
.FirstOrDefault(i => i.Contains("Microsoft.EntityFrameworkCore.Design", StringComparison.InvariantCulture));
var properties = metadata.Properties;
+ var outputPath = Path.GetFullPath(Path.Combine(properties[nameof(ProjectDir)]!, properties[nameof(OutputPath)]!));
+ CopyBuildHost(runtimeCopyLocalItems, outputPath);
+
var platformTarget = properties[nameof(PlatformTarget)];
if (platformTarget.Length == 0)
{
@@ -126,6 +131,50 @@ private record class ProjectMetadata
public Dictionary[]> Items { get; set; } = null!;
}
+ private static void CopyBuildHost(
+ Dictionary[] runtimeCopyLocalItems,
+ string targetDir)
+ {
+ var msbuildWorkspacesItem = runtimeCopyLocalItems.FirstOrDefault(item =>
+ string.Equals(item["Filename"], "Microsoft.CodeAnalysis.Workspaces.MSBuild", StringComparison.OrdinalIgnoreCase));
+
+ if (msbuildWorkspacesItem == null
+ || !msbuildWorkspacesItem.TryGetValue("CopyLocal", out var copyLocal)
+ || !string.Equals(copyLocal, "true", StringComparison.OrdinalIgnoreCase)
+ || !msbuildWorkspacesItem.TryGetValue("FullPath", out var fullPath)
+ || string.IsNullOrEmpty(fullPath))
+ {
+ return;
+ }
+
+ var contentFilesPath = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(fullPath)!, "..", "..", "contentFiles", "any", "any"));
+ CopyDirectoryRecursive(contentFilesPath, targetDir);
+ }
+
+ private static void CopyDirectoryRecursive(string sourceDir, string targetDir)
+ {
+ var directory = new DirectoryInfo(sourceDir);
+ if (!directory.Exists)
+ {
+ return;
+ }
+
+ Directory.CreateDirectory(targetDir);
+ foreach (var file in directory.GetFiles())
+ {
+ var filePath = Path.Combine(targetDir, file.Name);
+ if (!File.Exists(filePath))
+ {
+ file.CopyTo(filePath, overwrite: false);
+ }
+ }
+
+ foreach (var subDir in directory.GetDirectories())
+ {
+ CopyDirectoryRecursive(subDir.FullName, Path.Combine(targetDir, subDir.Name));
+ }
+ }
+
public void Build(IEnumerable? additionalArgs)
{
var args = new List { "build" };
diff --git a/src/ef/ReflectionOperationExecutor.cs b/src/ef/ReflectionOperationExecutor.cs
index ca4997884ce..9314a4326dd 100644
--- a/src/ef/ReflectionOperationExecutor.cs
+++ b/src/ef/ReflectionOperationExecutor.cs
@@ -7,6 +7,7 @@
using Microsoft.EntityFrameworkCore.Design.Internal;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Tools.Properties;
+
#if NET
using System.Runtime.Loader;
#endif
@@ -58,18 +59,13 @@ public ReflectionOperationExecutor(
AppDomain.CurrentDomain.AssemblyResolve += ResolveAssembly;
#if NET
- _commandsAssembly = AssemblyLoadContext.LoadFromAssemblyName(new AssemblyName(DesignAssemblyName));
+ _commandsAssembly = DesignAssemblyPath != null
+ ? AssemblyLoadContext.LoadFromAssemblyPath(DesignAssemblyPath)
+ : AssemblyLoadContext.LoadFromAssemblyName(new AssemblyName(DesignAssemblyName));
#else
- if (DesignAssemblyPath != null)
- {
- var assemblyPath = Path.GetDirectoryName(DesignAssemblyPath);
- assemblyPath = Path.Combine(assemblyPath, DesignAssemblyName + ".dll");
- _commandsAssembly = Assembly.LoadFrom(assemblyPath);
- }
- else
- {
- _commandsAssembly = Assembly.Load(DesignAssemblyName);
- }
+ _commandsAssembly = DesignAssemblyPath != null
+ ? Assembly.LoadFrom(DesignAssemblyPath)
+ : Assembly.Load(DesignAssemblyName);
#endif
var reportHandlerType = _commandsAssembly.GetType(ReportHandlerTypeName, throwOnError: true, ignoreCase: false)!;
@@ -109,16 +105,12 @@ protected AssemblyLoadContext AssemblyLoadContext
return _assemblyLoadContext;
}
- if (DesignAssemblyPath != null)
+ AssemblyLoadContext.Default.Resolving += (context, name) =>
{
- AssemblyLoadContext.Default.Resolving += (context, name) =>
- {
- var assemblyPath = Path.GetDirectoryName(DesignAssemblyPath)!;
- assemblyPath = Path.Combine(assemblyPath, name.Name + ".dll");
- return File.Exists(assemblyPath) ? context.LoadFromAssemblyPath(assemblyPath) : null;
- };
- _assemblyLoadContext = AssemblyLoadContext.Default;
- }
+ var assemblyPath = Path.Combine(AppBasePath, name.Name + ".dll");
+ return File.Exists(assemblyPath) ? context.LoadFromAssemblyPath(assemblyPath) : null;
+ };
+ _assemblyLoadContext = AssemblyLoadContext.Default;
return AssemblyLoadContext.Default;
}
@@ -136,18 +128,13 @@ public override string? EFCoreVersion
Assembly? assembly = null;
#if NET
- assembly = AssemblyLoadContext.LoadFromAssemblyName(new AssemblyName(DesignAssemblyName));
+ assembly = DesignAssemblyPath != null
+ ? AssemblyLoadContext.LoadFromAssemblyPath(DesignAssemblyPath)
+ : AssemblyLoadContext.LoadFromAssemblyName(new AssemblyName(DesignAssemblyName));
#else
- if (DesignAssemblyPath != null)
- {
- var assemblyPath = Path.GetDirectoryName(DesignAssemblyPath);
- assemblyPath = Path.Combine(assemblyPath, DesignAssemblyName + ".dll");
- assembly = Assembly.LoadFrom(assemblyPath);
- }
- else
- {
- assembly = Assembly.Load(DesignAssemblyName);
- }
+ assembly = DesignAssemblyPath != null
+ ? Assembly.LoadFrom(DesignAssemblyPath)
+ : Assembly.Load(DesignAssemblyName);
#endif
_efcoreVersion = assembly.GetCustomAttribute()
?.InformationalVersion;
diff --git a/src/ef/ef.csproj b/src/ef/ef.csproj
index eeb9b64e468..bc690085b1c 100644
--- a/src/ef/ef.csproj
+++ b/src/ef/ef.csproj
@@ -29,16 +29,6 @@
-
-
-
- $(NoWarn);NU1903
-
-
-
-
-
-
diff --git a/test/Directory.Packages.props b/test/Directory.Packages.props
index fb0eada61df..576e68d96da 100644
--- a/test/Directory.Packages.props
+++ b/test/Directory.Packages.props
@@ -4,12 +4,11 @@
-
-
-
+
+
+
-
-
+
@@ -18,10 +17,10 @@
-
-
-
-
+
+
+
+