TrackableEntities / EntityFrameworkCore.Scaffolding.Handlebars

Scaffold EF Core models using Handlebars templates.
MIT License
210 stars 53 forks source link

CodeTemplates folder not copied to output directory on build #186

Closed johnwc closed 2 years ago

johnwc commented 2 years ago

Describe the bug When using the --startup-project option to create the db models and db context in a library, but use the connection string from the main project using "Name=ConnectionString:xxx". I have to put the ConfigureDesignTimeServices in the main project, and we get the System.IO.DirectoryNotFoundException: Could not find a part of the path '....MainProject\bin\Debug\net5.0\CodeTemplates\CSharpDbContext\Partials\DbImports.hbs'. exception.

Expected behavior Expect it to use the current project, the library project in this case; for checking for IDesignTimeServices class. As well as using the current project for creating the CodeTemplates directory.

To Reproduce

  1. Create Library project
  2. Create Console/Web project, referencing library project.
  3. Create connection string in Console/Web project named xyz.
  4. Add all required EF core nuget packages to library and console/web project.
  5. Create IDesignTimeServices in console/web project.
  6. Run dotnet ef dbcontext scaffold "Name=ConnectionStrings:xyz" "<Your DB provider class>" -d --force -o DAL -c XyzContextDb --startup-project ..\MainApp from library project's directory.
tonysneed commented 2 years ago

@johnwc The way the EF Core CLI works is that it uses a .NET Core app or library to do its magic. This is where the IDesignTimeServices class needs to reside, and it is the place from which you need to run the dotnet ef dbcontext scaffold command, or where you need to direct the --startup-project command, as stated in the docs.

I have a sample project with instructions on how to do this. Please have a look and let me know if this helps clarify.

johnwc commented 2 years ago

There is two issues pointed out. The main issue is with the DB exception when trying to use connecting string by name from the start up project.

tonysneed commented 2 years ago

Where is your appSettings.json file located, which contains connection string name? It should be in your MainApp.

johnwc commented 2 years ago

It is in the project that is pointed at via the --startup-project option, aka the MainApp in the example command line.

tonysneed commented 2 years ago

I was able to reproduce the issue here. Will look into the cause.

tonysneed commented 2 years ago

The problem is taking place at build-time, not runtime. And it has nothing to do with the --startup-project option or using a connection string name.

The project file for EntityFrameworkCore.Scaffolding.Handlebars has a section that copies hbs templates to a CodeTemplates folder in the build output directory. For example:

<None Update="CodeTemplates\CSharpDbContext\Partials\DbImports.hbs">
    <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>

Sometimes dotnet build does not result in the files being copied. When they are not present, this results in a runtime exception when the the library attempts to copy them to the project directory.

I will investigate this as a bug with NuGet / dotnet build. In the meantime, you can get around this by simply copying the CodeTemplates folder to the project root. If it is there, no I/O error will take place.

tonysneed commented 2 years ago

Found out how to fix the problem. Created a demo project on how to copy files from a NuGet package to an output directory.

I'll create a PR to fix the problem for EntityFrameworkCore.Scaffolding.Handlebars.