The Pitfalls of using EntityFramework in an nx-dotnet environment (with solutions)
Tags: nx, nxdotnet, dotnet, dotnetcore
Published: 2023-04-10 16:09:10

## Nx + EFCore = Problems
When using the Nx-dotnet plugin with Entity Framework Core, you may encounter an issue where Entity Framework (EF) is unable to locate the EntityFrameworkCore.targets file when using the `dotnet ef *` CLI commands. 

This can result in a cryptic error message such as:

``` pwsh
error MSB4057: The target "GetEFProjectMetadata" does not exist in the project.

Unable to retrieve project metadata. Ensure it's an SDK-style project. 

If you're using a custom BaseIntermediateOutputPath or MSBuildProjectExtensionsPath values, 
Use the --msbuildprojectextensionspath option.
```

In a nutshell this error means that EF cannot find some required meta files. It occurs because the Nx-dotnet plugin creates a `Directory.Build.props` file in the project root which overrides the ProjectRelativePath and BaseOutputPath properties in all project files. These settings instruct the compiler to build assemblies in specific locations. Nxdotnet does this to ensure that all builds go into the dist folder, keeping in situ with the Nx folder structure.

Entity Framework Core has no knowledge of Nx nor does it care about the Nx non-standard folder structure. It is therefore unable to locate the necessary meta-data. It expects target files to reside in the obj folder in standard dotnet builds. However as we're using an overridden folder structure Entity Framework is unable to locate the files.

To resolve this issue, I personally used the following solution:

## A Simple Solution

1. *Copy* (don't move) the Directory.Build.props file from the project root into the apps folder of your solution.

2. In the copied `Directory.Build.props` file, change the following line:

``` xml
<RepoRoot>$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)'))</RepoRoot>
```
to:

``` xml
<RepoRoot>$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)../../'))</RepoRoot>
```

This will ensure that the build process uses the parent directory of the apps folder as the root of the repository.

3. Remove the following lines from the original Directory.Build.props file located in the project root:

``` xml
<BaseOutputPath>$(RepoRoot)dist/$(ProjectRelativePath)</BaseOutputPath>
<OutputPath>$(BaseOutputPath)</OutputPath>
<BaseIntermediateOutputPath>$(RepoRoot)dist/intermediates/$(ProjectRelativePath)/obj</BaseIntermediateOutputPath>
```

This will cause all Nx apps to be published into the dist folder along with their referenced library DLL binaries. 

The library projects however can still build into their own `bin` and `obj` directories as per usual. This will keep the Entity Framework Core Cli happy, and you can continue using it as per usual.

By following these steps, you can ensure that Entity Framework Core can locate the necessary metadata during the migration process, while still maintaining a consistent output structure for your solution.

Hopefully you're now aware of the root cause (yes, the pun was intentional) of the issue. You should now be equipped with the required knowledge to create the perfect solution for your specific needs.