msawczyn/EFDesigner

Generated code not being output to the override output directory

rlarik opened this issue · 8 comments

I created a separate project for the model and created subdirectories (Entities, Enums and Context). Apart from the general object output directory, which is set to Entities, I also set an output directory per entity.

I have an entity called Address and the output directory is set to Entities/PartyAddresses, this directory exists and this was an option inside the combobox.

Upon code generation all entities get generated to the root of the Entities folder.

Hi @rlarik ,

I've never seen that happen. Is that the only class where you're having problems? Are all other classes getting generated into their proper directory?

Every class ends up in the root. Using Visual Studio 2017 v15.8.7

I will update Visual Studio and see if this problem persists.

Sadly, updating Visual Studio did not change this behavior. It seems like VS ignores the overrides and prioritizes the general output directory setting.

This is most intriguing. Is it possible for you to put together a small sample that exhibits the problem and attach it to a comment here? The work to write to the different directories is done in the T4 templates, not the designer itself - specifically the Process method in MultipleOutputHelper.ttinclude in the extension's install directory.

If you could send that, I could step through and see what's going on, since I really can't reproduce what you're seeing. Easiest would be to just zip up the solution's directory and attach.

EFVisualDesignerTest.zip

Attached. All settings default except for the output directories.

I have tried this both at home and at work (both Community edition), same behavior. I feel like I am missing something. I did locate the MultipleOutputHelper.ttinclude file, everything seems to be in place.

This was a good catch! The issue is in EF6Designer.ttinclude (and EFCoreDesigner.ttinclude, depending on your target EF type). Having the example was extremely helpful.

Right at the top of each of these files is the code to determine the output directory name - and it doesn't appear that it's taking any class-level overrides into account. So the code currently is

   // Entities

   foreach (ModelClass modelClass in modelRoot.Classes)
   {
      string dir = modelClass.IsDependentType ? modelRoot.StructOutputDirectory : modelRoot.EntityOutputDirectory;
      manager.StartNewFile(Path.Combine(dir, $"{modelClass.Name}.{modelRoot.FileNameMarker}.cs"));
      WriteClass(modelClass);
   }

   // Enums

   foreach (ModelEnum modelEnum in modelRoot.Enums)
   {
      manager.StartNewFile(Path.Combine(modelRoot.EnumOutputDirectory, $"{modelEnum.Name}.{modelRoot.FileNameMarker}.cs"));
      WriteEnum(modelEnum);
   }

when it should be

   // Entities

   foreach (ModelClass modelClass in modelRoot.Classes)
   {
      string dir = modelClass.IsDependentType ? modelRoot.StructOutputDirectory : modelRoot.EntityOutputDirectory;
      if (!string.IsNullOrEmpty(modelClass.OutputDirectory)) dir = modelClass.OutputDirectory;
      manager.StartNewFile(Path.Combine(dir, $"{modelClass.Name}.{modelRoot.FileNameMarker}.cs"));
      WriteClass(modelClass);
   }

   // Enums

   foreach (ModelEnum modelEnum in modelRoot.Enums)
   {
      string dir = !string.IsNullOrEmpty(modelEnum.OutputDirectory) ? modelEnum.OutputDirectory : modelRoot.EnumOutputDirectory;
      manager.StartNewFile(Path.Combine(dir, $"{modelEnum.Name}.{modelRoot.FileNameMarker}.cs"));
      WriteEnum(modelEnum);
   }

You can make that fix immediately in your installation; I've made it in the templates for the next release. It may be that you're the first person to use the directory override feature! Looking at my test harness, I see as well that I didn't add the test for it, because I should have caught that before this :-(

Thanks for the help!

I am glad I could help resolve the issue! Thanks a lot for the great work you put into this.
Works like a charm now.