ErikEJ / EFCorePowerTools

Entity Framework Core Power Tools - reverse engineering, migrations and model visualization in Visual Studio & CLI
MIT License
2.13k stars 294 forks source link

Data changes to Datum #235

Closed davidhendrickmb closed 5 years ago

davidhendrickmb commented 5 years ago

Hi, I have multiple tables that end in "Data". The first Reverse Engineer process worked perfectly, but when I run it again, all the tables are now called "Datum". Do you know why this might be?

Thanks, David

ErikEJ commented 5 years ago

You are using Pluralization?

davidhendrickmb commented 5 years ago

I have always used Pluralization but this has just started happening.

davidhendrickmb commented 5 years ago

Is there any way I can prevent this pluralization?

ErikEJ commented 5 years ago

I have updated the pluralizer, and there is no way to modify it - basically the conclusion is there is no perfect pluralizer. I will consider making the previous pluralizer availalable as an option.

ErikEJ commented 5 years ago

Closing this, pls vote for #227 if you want this to happen (or even submit a PR that makes the old pluralizer availabale as an option)

ErikEJ commented 5 years ago

I have added an option to use the EF6 pluralizer in the latest daily build

Add this to efpt.config.json:

  "UseLegacyPluralizer": true,

Please let me know if that solves your issue

jostapotcf commented 5 years ago

Hi Erik,

First, thanks for the tool. It was saving us a great deal of time in re-genning our model.

Unfortunately, the latest changes in the pluralization are resulting in a "hot mess".

Our work flow would typically go:

1) Edit database. 2) Fire up EFPT, make sure any new tables are ticked 3) Click through to OK.

Prior to the latest builds, this would always result in nice neat changesets.

Now we're in a situation where half the model is being "added", while the other half has your new comments as "changed". We can live with the latter, but the adds mean a mess of refactoring on our part. (To be clear, the half being 'added' are due to pluralization changes)

We've tried the UseLegacyPluralizer option, and this is not resolving the issue.

We're going to muscle through the refactor, but thought you ought to know.

-joel

PS> To be a little more clear,

Table -> Amca207motorDolPerformanceConstants Was -> Amca207motorDolPerformanceConstants (with old pluralization on) Is Now Coming up as -> Amca207motorDolPerformanceConstant

ErikEJ commented 5 years ago

Hmmm... Sorry to hear that. This weekend the daily build will switch to using Humanizer for pluralization. Maybe that will work better for you?

jostapotcf commented 5 years ago

Quick response Erik, it's middle of the afternoon here on a Friday, so we can definitely work on something else and try the new build Monday.

(see my edit to the comment above for what's going on)

Much thanks again, and we'll get back to you next week.

ErikEJ commented 5 years ago

For anyone following this: I have now switched to using Humanizer in the latest daily build (and also have the option to use the EF6 pluralizer)

jostapotcf commented 5 years ago

Attached below is the full config.json I used to get try and get back to where we were. I didn't snip the Tables property so you could see the full table list we're bringing over (and what sorts of naming are working fine)

Would expect a changeset with 5 changes.

But got:

Part of the recent builds was including a "Generated" comment, so that's where almost all the changes are coming in now.

The config below fixed almost all our issues from last week, exception one.

In the config, you'll see a "m.Phases" table. Previously it had been genning as:

    public partial class Phase
    {
        //snip
    }

but is now coming across as:

    public partial class Phas
    {
        //snip
    }

No joke, that's copy/pasted.

Strangely, the context name for the DbSet was only partly pluralized/unpluralized:

        public virtual DbSet<Phas> Phases { get; set; }

Note the type is 'Phas' and the name is 'Phases'.

I noticed in the Wiki there is the ability to edit the config to target specific class names. Unless advised to do otherwise, I'm going to path this one exception via config.

I've only gotten as far as gen'ing the model, and haven't even run the compiler yet, or our unit tests . We may have additional issues. If so I'll report on new issues.

Thanks again guys. Let me know if there is anything else I can do or share with you.

efpt.config.json

{
  "ContextClassName": "CuratedDb",
  "DefaultDacpacSchema": null,
  "DoNotCombineNamespace": false,
  "IdReplace": false,
  "IncludeConnectionString": true,
  "OutputPath": "Models",
  "ProjectRootNamespace": "TCF.Performance.Data",
  "SelectedHandlebarsLanguage": 0,
  "SelectedToBeGenerated": 0,
  "Tables": [
    {
      "HasPrimaryKey": true,
      "Name": "dbo.Certifications"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.CertifyingBodies"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.FanAirPerformanceData"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.FanAirPerformances"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.FanArrangements"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.FanClasses"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.FanDischargeDirections"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.FanDischarges"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.FanDriveMethods"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.FanModelMotorLists"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.FanModels"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.FanPerformanceCorrectionConstants"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.FanPerformanceCorrections"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.FanProductAirPerformances"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.FanProductCertificationForNameplates"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.FanProductCertifications"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.FanProductImpellers"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.FanProductPerformanceCorrections"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.FanProductPerformanceCorrectionVariables"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.FanProducts"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.FanProductSoundDataSets"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.FanSizes"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.FanSoundDataRecords"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.FanSoundDataSetRecords"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.FanSoundDataSets"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.FanSoundDataValues"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.FanSoundMethods"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.FanSoundTypes"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.ImpellerRPMDerateFactors"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.ImpellerRPMDerateSets"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.Impellers"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.ImpellerTypes"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.InducedFlowFanProperties"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.Materials"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.VentilatorModels"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.VentilatorPerformanceCorrectionConstants"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.VentilatorPerformanceCorrections"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.VentilatorPerformanceFactor"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.VentilatorProductPerformanceCorrections"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.VentilatorProductPerformanceCorrectionVariables"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.VentilatorProducts"
    },
    {
      "HasPrimaryKey": true,
      "Name": "dbo.VentilatorSizes"
    },
    {
      "HasPrimaryKey": true,
      "Name": "lu.AMCA207MotorDolPerformanceConstants"
    },
    {
      "HasPrimaryKey": true,
      "Name": "lu.AMCA207MotorEfficiencies"
    },
    {
      "HasPrimaryKey": true,
      "Name": "lu.AMCA207MotorScopes"
    },
    {
      "HasPrimaryKey": true,
      "Name": "lu.AMCA207MotorWithVfdPerformanceConstants"
    },
    {
      "HasPrimaryKey": true,
      "Name": "lu.AMCA207VfdPerformanceConstants"
    },
    {
      "HasPrimaryKey": true,
      "Name": "lu.AMCA208FanTypes"
    },
    {
      "HasPrimaryKey": true,
      "Name": "lu.AMCA208TestConfigurations"
    },
    {
      "HasPrimaryKey": true,
      "Name": "lu.AMCALicenses"
    },
    {
      "HasPrimaryKey": true,
      "Name": "lu.FanModelCrossovers"
    },
    {
      "HasPrimaryKey": true,
      "Name": "lu.FanSoundBladeAdjustments"
    },
    {
      "HasPrimaryKey": true,
      "Name": "lu.FanSoundBladeAdjustmentValues"
    },
    {
      "HasPrimaryKey": true,
      "Name": "lu.ModelCategories"
    },
    {
      "HasPrimaryKey": true,
      "Name": "lu.SoneLoudnessIndices"
    },
    {
      "HasPrimaryKey": true,
      "Name": "m.Efficiencies"
    },
    {
      "HasPrimaryKey": true,
      "Name": "m.Enclosures"
    },
    {
      "HasPrimaryKey": true,
      "Name": "m.ExplosionProofClassGroups"
    },
    {
      "HasPrimaryKey": true,
      "Name": "m.FanProductFrameSizes"
    },
    {
      "HasPrimaryKey": true,
      "Name": "m.FanProductMotorNameplates"
    },
    {
      "HasPrimaryKey": true,
      "Name": "m.FanProductSpeedControlRPMs"
    },
    {
      "HasPrimaryKey": true,
      "Name": "m.FrameSizes"
    },
    {
      "HasPrimaryKey": true,
      "Name": "m.FrameStandards"
    },
    {
      "HasPrimaryKey": true,
      "Name": "m.FrameTypes"
    },
    {
      "HasPrimaryKey": true,
      "Name": "m.Frequencies"
    },
    {
      "HasPrimaryKey": true,
      "Name": "m.InputServices"
    },
    {
      "HasPrimaryKey": true,
      "Name": "m.MotorListNameplates"
    },
    {
      "HasPrimaryKey": true,
      "Name": "m.MotorLists"
    },
    {
      "HasPrimaryKey": true,
      "Name": "m.MotorManufacturers"
    },
    {
      "HasPrimaryKey": true,
      "Name": "m.MotorManufacturerTestData"
    },
    {
      "HasPrimaryKey": true,
      "Name": "m.MotorManufacturerTests"
    },
    {
      "HasPrimaryKey": true,
      "Name": "m.MotorModels"
    },
    {
      "HasPrimaryKey": true,
      "Name": "m.MotorTechnologies"
    },
    {
      "HasPrimaryKey": true,
      "Name": "m.NameplateInputServices"
    },
    {
      "HasPrimaryKey": true,
      "Name": "m.NameplatePowers"
    },
    {
      "HasPrimaryKey": true,
      "Name": "m.NameplateRPMs"
    },
    {
      "HasPrimaryKey": true,
      "Name": "m.Nameplates"
    },
    {
      "HasPrimaryKey": true,
      "Name": "m.Phases"
    },
    {
      "HasPrimaryKey": true,
      "Name": "m.Poles"
    },
    {
      "HasPrimaryKey": true,
      "Name": "m.RPMs"
    },
    {
      "HasPrimaryKey": true,
      "Name": "m.TestedMotorConfigurations"
    },
    {
      "HasPrimaryKey": true,
      "Name": "m.TestedMotorDataPoints"
    },
    {
      "HasPrimaryKey": true,
      "Name": "m.TestedMotorTriangles"
    },
    {
      "HasPrimaryKey": true,
      "Name": "m.Voltages"
    },
    {
      "HasPrimaryKey": true,
      "Name": "m.WiringConfigurations"
    },
    {
      "HasPrimaryKey": true,
      "Name": "poly.MinimumReynoldsNumberFanModels"
    },
    {
      "HasPrimaryKey": true,
      "Name": "poly.MinimumReynoldsNumbers"
    }
  ],
  "UseDatabaseNames": false,
  "UseFluentApiOnly": true,
  "UseHandleBars": false,
  "UseInflector": true,
  "UseLegacyPluralizer": true
}
jostapotcf commented 5 years ago

With the following efpt.renaming.json, the erroneous Phas class is not created, and AAAPotato is created as expected.

[
  {
    "UseSchemaName": false,
    "SchemaName": "m",
    "Tables": [
      {
        "Name": "Phases",
        "NewName": "AAAPotato"
      }
    ]
  }
]

With the following efpt.renaming.json, the erroneous Phas class is created, and the desired Phases class is not gen'd.

[
  {
    "UseSchemaName": false,
    "SchemaName": "m",
    "Tables": [
      {
        "Name": "Phases",
        "NewName": "Phases"
      }
    ]
  }
]

So the renaming file, as used today isn't a workaround (at least the way I've used it).

I will say this most recent build is much closer and we can work around the quirks.

ErikEJ commented 5 years ago

Thanks for the update @jostapotcf

jostapotcf commented 5 years ago

(make sure you are fully caffeinated before reading this)

Sorry to keep beating this one, but I think I did figure out why the one table Phases was having a problem.

USE [CuratedPhase1]

/****** Object:  Table [m].[Phases]    Script Date: 8/12/2019 12:15:40 PM ******/
SET ANSI_NULLS ON

SET QUOTED_IDENTIFIER ON

CREATE TABLE [m].[Phases](
    [Phase] [tinyint] NOT NULL,
 CONSTRAINT [PK_Phases] PRIMARY KEY CLUSTERED 
(
    [Phase] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
)

GO

A perfect storm of pluralization/depluralization and a property not being able to have the same name as the class.

Phases --> Phase

wants to become (thanks to depluralization)

Phase --> Phase

which it can't (C#), it was doing

Phase --> Phase1

but is now doing

Phas --> Phase

You could argue this one is a fringe case.

Fixable by changing the column name to "PhaseValue".

ErikEJ commented 1 year ago

Datum issue fixed in latest daily build