Skip to content

Commit

Permalink
Document the SDK breaking change affecting EF tools (#4934)
Browse files Browse the repository at this point in the history
  • Loading branch information
AndriySvyryd authored Jan 21, 2025
1 parent c3e2876 commit 2cb247b
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 9 deletions.
3 changes: 2 additions & 1 deletion entity-framework/core/cli/msbuild.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: EF Core MSBuild tasks - EF Core
description: Reference guide for the Entity Framework Core .NET MSBuild tasks
author: AndriySvyryd
ms.date: 11/08/2024
ms.date: 01/17/2025
uid: core/cli/msbuild
---

Expand Down Expand Up @@ -40,6 +40,7 @@ If the project specifies `<PublishAot>true</PublishAot>` then by default the MSB

## Limitations

* When using the integration during the `publish` stage also set the rid in the startup project (e.g. \<RuntimeIdentifier\>win-x64\</RuntimeIdentifier\>)
* A different startup project cannot be specified when using this approach as it would introduce an inverse build dependency. This means that the context project needs to be autosuficient in terms of configuration, so if your app normally configures the context using a host builder in a different project you'd need to [implement _IDesignTimeDbContextFactory&lt;TContext&gt;_](xref:core/cli/dbcontext-creation#from-a-design-time-factory) in the context project.
* Since the project needs to be compilable before the compiled model is generated this approach doesn't support partial method implementations for customization of the compiled model.
* Currently, this will always generate additional code in the compiled model that's required for NativeAOT. If you are not planning to enable NativeAOT then [generate the compiled model using the CLI tools](xref:core/cli/dotnet#optimize).
Expand Down
9 changes: 2 additions & 7 deletions entity-framework/core/miscellaneous/internals/tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Design-time Tools Architecture - EF Core
description: The architecture of design-time tools in Entity Framework Core
author: SamMonoRT
ms.date: 11/27/2023
ms.date: 01/17/2025
uid: core/miscellaneous/internals/tools
---
# Design-time Tools Architecture
Expand All @@ -23,12 +23,7 @@ There are two primary inputs to this command: the startup project and the target

It reads information about the projects by injecting an MSBuild .targets file and calling the custom MSBuild target. The .targets file is compiled into dotnet-ef as an embedded resource. The source is located at [src/dotnet-ef/Resources/EntityFrameworkCore.targets](https://github.com/dotnet/efcore/blob/main/src/dotnet-ef/Resources/EntityFrameworkCore.targets).

It has a bit of logic at the beginning to handle multi-targeting projects. Essentially, it just picks the first target framework and re-invokes itself. After a single target framework has been determined, it writes several MSBuild properties like AssemblyName, OutputPath, RootNamespace, etc. to a temporary file that dotnet-ef then reads.

> [!TIP]
> .NET 8 adds a new, streamlined way to read MSBuild properties that will enable us to remove this .targets file. See issue [#32113](https://github.com/dotnet/efcore/issues/32113).
We need to inject this target into both the startup and target project. We do that by leveraging an MSBuild hook created for NuGet and other package managers. That hook automatically loads any file under `$(MSBuildProjectExtensionsPath)` with a name matching the pattern `$(MSBuildProjectName).*.targets`. Unfortunately, we don't know the actual value of the MSBuildProjectExtensionsPath property, and we need it before we can read any MSBuild properties. So, we assume it's set to the default value of `$(MSBuildProjectDirectory)\obj`. If it's not, the user must specify it using the `--msbuildprojectextensionspath` option.
It has a bit of logic at the beginning to handle multi-targeting projects. Essentially, it just picks the first target framework and re-invokes itself. After a single target framework has been determined, it gets several MSBuild properties like AssemblyName, OutputPath, RootNamespace, etc.

After we've collected the project information, we compile the startup project. We assume that the target project will also be compiled transitively.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Breaking changes in EF Core 9 (EF9) - EF Core
description: List of breaking changes introduced in Entity Framework Core 9 (EF9)
author: ajcvickers
ms.date: 12/17/2024
ms.date: 01/17/2025
uid: core/what-is-new/ef-core-9.0/breaking-changes
---

Expand All @@ -27,6 +27,7 @@ EF Core 9 targets .NET 8. This means that existing applications that target .NET
|:----------------------------------------------------------------------------------------------------------|------------|
| [Exception is thrown when applying migrations if there are pending model changes](#pending-model-changes) | High |
| [Exception is thrown when applying migrations in an explicit transaction](#migrations-transaction) | High |
| [`Microsoft.EntityFrameworkCore.Design` not found when using EF tools](#tools-design) | Medium |
| [`EF.Functions.Unhex()` now returns `byte[]?`](#unhex) | Low |
| [SqlFunctionExpression's nullability arguments' arity validated](#sqlfunctionexpression-nullability) | Low |
| [`ToString()` method now returns empty string for `null` instances](#nullable-tostring) | Low |
Expand Down Expand Up @@ -114,6 +115,48 @@ Otherwise, if your scenario requires an explicit transaction and you have other
options.ConfigureWarnings(w => w.Ignore(RelationalEventId.MigrationsUserTransactionWarning))
```

## Medium-impact changes

<a name="tools-design"></a>

### `Microsoft.EntityFrameworkCore.Design` not found when using EF tools

[Tracking Issue #35265](https://github.com/dotnet/efcore/issues/35265)

#### Old behavior

Previusly, the EF tools required `Microsoft.EntityFrameworkCore.Design` to be referenced in the following way.

```XML
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="*.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
```

#### New behavior

Starting with .NET SDK 9.0.200 an exception is thrown when an EF tool is invoked:
> :::no-loc text="Could not load file or assembly 'Microsoft.EntityFrameworkCore.Design, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.":::
#### Why

EF tools were relying on an undocumented behavior of .NET SDK that caused private assets to be included in the generated `.deps.json` file. This was fixed in [sdk#45259](https://github.com/dotnet/sdk/pull/45259). Unfortunately, the EF change to account for this doesn't meet the servicing bar for EF 9.0.x, so it will be fixed in EF 10.

#### Mitigations

As a workaround before EF 10 is released you can mark the `Design` assembly reference as publishable:

```XML
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<Publish>true</Publish>
</PackageReference>
```

This will include it in the generated `.deps.json` file, but has a side effect of copying `Microsoft.EntityFrameworkCore.Design.dll` to the output and publish folders.

## Low-impact changes

<a name="unhex"></a>
Expand Down

0 comments on commit 2cb247b

Please sign in to comment.