Skip to content

Proposal: Specify columns to ignore during reverse engineering #572

Closed

Description

@sm15455

Hi,

when scaffolding from database, I often need to map a property to an enum type and not to its database column type. I know I can use handlebars template, but I have another suggestion which could make life easier. Would it be possible to expand the renaming file (or create a new one) to specify columns to ignore during import? This would allow me to use partial classes to define properties for those columns and partial method in OnModelCreating to define their mapping. I know such task would not be high in the priority list, so I would be more than happy to contribute.

Activity

  1. ErikEJ commented on Nov 11, 2020

    @ErikEJ
    Owner

    Please give an example of your modifications if a column was not included.

  2. sm15455 commented on Nov 11, 2020

    @sm15455
    CollaboratorAuthor
    //EFPT generated code
    public partial class Person
    {
      public int Id { get; set; }
      public string Name { get; set; }
    }
    
    //my custom code
    public partial class Person
    {
      public Gender Gender { get; set; }
    }
    
    public enum Gender 
    {
      Male,
      Female,
      Other
    }
    
    public partial class MyDbContext
    {
      void OnModelCreatingPartial(ModelBuilder modelBuilder)
      {
        modelBuilder.Entity<Person>(entity => 
        {
          entity.Property(e => e.Gender)
            .whatevermapping();
        });
      }
    }
    
  3. ErikEJ commented on Nov 12, 2020

    @ErikEJ
    Owner

    Had a closer look at this, looks like an approach to try would be to implement https://github.com/dotnet/efcore/blob/main/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs#L299 and register this override when building the service provider, if a list of columns to exclude are available, then modify the DatabaseTable model by removing the excluded columns.

    we would need a way to pass the list of columns to exclude to this class.

    The list of columns to exclude could be under each Table in the tables list in efpt.config.json.

    PRs accepted.

  4. sm15455 commented on Nov 12, 2020

    @sm15455
    CollaboratorAuthor

    That's the file I was looking at. I'm glad we have same idea.
    I cloned the repository and will start working on a PR as soon as I can. The only problem is that I never created a VS Extension before so it will take some time before everything is setup.

  5. ErikEJ commented on Nov 12, 2020

    @ErikEJ
    Owner

    @sm15455 As long as you have the Extensibility workload installed in Visual Studio, set EFCorePowerTools project as startup and set build platform to x86, it should be as simple a pressing F5!

    Please feel free to discuss any design concerns before getting in too deep.

  6. ErikEJ commented on Nov 12, 2020

    @ErikEJ
    Owner

    For testing just scaffolding, make the efreveng project your startup project!

  7. ErikEJ commented on Nov 12, 2020

    @ErikEJ
    Owner

    Duplicate of #353

  8. paul1923 commented on Nov 13, 2020

    @paul1923

    Another use case when ignoring column names is helpful is Temporal Tables, ie: [SysEndTime], [SysStartTime] columns

  9. ErikEJ commented on Nov 13, 2020

    @ErikEJ
    Owner

    @paul1923 Sure, but you can also mark them hidden.

  10. sm15455 commented on Nov 13, 2020

    @sm15455
    CollaboratorAuthor

    @ErikEJ I'm slowly moving on.

    On The reveng side I did the following changes

    • Modified the TableInformationModel class adding the ExcludedColumns (string[]) property.
    • Inherited from RelationalScaffoldingModelFactory and overriden the VisitTable method to remove excluded columns before the visitor creates the entity builder for the table.
    • Added the new scaffolder to the service provider builder.

    Now I need to work on the UI side. I should:

    • Serialize and deserialize the ExcludedColumns property as a property of a table in the eft.config.json.
    • create a hierarchical view of the tables where user can view all tables and their columns. All columns for a table should be selected and the user must select those he wants to exclude.
    • Remember the user selection when UI is reloaded (it happens now for table selection and must do the same for columns)

    The problem is that TableInformationModel is directly used in the ITableInformationViewModel model so I can't use the ExcludedColumns property because in the UI it's not a simple list of strings, but a list of (string, bool) (needed for selection). The most conservative approach I can think of is to add a ExcludedColumns property in the ITableInformationViewModel and then write code to map it to and from ExcludedColumns property in the TableInformationModel. Any thought on this?

  11. ErikEJ commented on Nov 13, 2020

    @ErikEJ
    Owner

    Fantastic!

    I suggest that we make it a manual feature for now, so folks can try it out, just make sure that we serialize and deserialize properly.

    Then we can also think about improving the View Model, possibly map to a class that is better suited for UI display than the TableInformationModel.

  12. ErikEJ commented on Nov 13, 2020

    @ErikEJ
    Owner

    Submitting a PR with that will also make the changes and code review much more manageable.

  13. 5 remaining items

  14. ErikEJ commented on Nov 14, 2020

    @ErikEJ
    Owner

    No worries, been there myself - let me know if you are unblocked.

  15. paul1923 commented on Nov 15, 2020

    @paul1923

    @ErikEJ

    Thanks for the tip on HIDDEN columns. I've opted instead to create another DbContext partial class for the fields I want ignored.

  16. sm15455 commented on Nov 16, 2020

    @sm15455
    CollaboratorAuthor

    @ErikEJ I close this issue as the feature is now implemented. I'll open a new one for the UI

  17. reopened this on Nov 16, 2020
  18. ErikEJ commented on Nov 16, 2020

    @ErikEJ
    Owner

    It is not in the daily build yet, hang in there...

  19. added a commit that references this issue on Nov 16, 2020
    f9df34b
  20. added a commit that references this issue on Nov 16, 2020
    b72d068
  21. ErikEJ commented on Nov 17, 2020

    @ErikEJ
    Owner

    @sm15455

    Some thoughts on next step:

    Create new class to exchange the table list (stop using TableInformation).
    Add columns to this class.

    Add columns to the output from TableList command if EFPT CLI tool.

    Extend TableInformation with a new, non-serialized List, where ColumnInformation has:

    string Name
    bool Excluded

    Construct the ExcludeColumns property when loading options, and set when saving options.

    Bind ColumnInfomation to UI - no idea how...

  22. ErikEJ commented on Aug 19, 2022

    @ErikEJ
    Owner

    Custom enum mapping is now available with EF Core 7 and T4 templates

  23. Colemartindale commented on Feb 15, 2023

    @Colemartindale

    @paul1923 Sure, but you can also mark them hidden.

    How do you mark Temporal tables as hidden?

  24. ErikEJ commented on Feb 15, 2023

    @ErikEJ
    Owner

    @Colemartindale exclude them??

  25. Colemartindale commented on Feb 15, 2023

    @Colemartindale

    My apologies.. I'm not following. Should this be done on the DB side or in the app itself?
    We recently updated our API to .NET & EF 6.0. Within our scaffolded DbContext file, the temporal tables now get included (when they didn't before) on our model builder.

    We have a context extension class that implements this method:

    partial void OnModelCreatingPartial(ModelBuilder modelBuilder) { modelBuilder.Entity<AnalysisMetric>(entity => {entity.Ignore("analysis_metric_HISTORY"); }); }

    but this doesn't seem to work

  26. ErikEJ commented on Feb 15, 2023

    @ErikEJ
    Owner

    Please create a new issue and share a repro script and I will have a look.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions