DEV Community

Cover image for The Pitfalls of using EntityFramework in an nx-dotnet environment (with solutions)
Kiran Randhawa
Kiran Randhawa

Posted on

The Pitfalls of using EntityFramework in an nx-dotnet environment (with solutions)

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:

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.
Enter fullscreen mode Exit fullscreen mode

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:

<RepoRoot>$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)'))</RepoRoot>
Enter fullscreen mode Exit fullscreen mode

to:

<RepoRoot>$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)../../'))</RepoRoot>
Enter fullscreen mode Exit fullscreen mode

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

  1. Remove the following lines from the original Directory.Build.props file located in the project root:
<BaseOutputPath>$(RepoRoot)dist/$(ProjectRelativePath)</BaseOutputPath>
<OutputPath>$(BaseOutputPath)</OutputPath>
<BaseIntermediateOutputPath>$(RepoRoot)dist/intermediates/$(ProjectRelativePath)/obj</BaseIntermediateOutputPath>
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (2)

Collapse
 
arthurfedotiev profile image
Arthur-Fedotiev • Edited

Thank you so so much for you extremely helpful article, mate!!!
I've got smth to add though:

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

You have to put it into the folder which contains your dotnet application, not to the apps folder where all of your applications are located - apps/ (at least that worked in my case and makes sense imo). Otherwise you are going to get an error when you are trying to build the app.

Collapse
 
simplifycomplexity profile image
Kiran Randhawa

Hey, I don't this site as often as I should do. Thank you for taking the time to post such an encouraging comment. I'm really glad that I could help you.