sjh37 / EntityFramework-Reverse-POCO-Code-First-Generator

EntityFramework Reverse POCO Code First Generator - Beautifully generated code that is fully customisable. This generator creates code as if you reverse engineered a database and lovingly created the code by hand. It is free to academics (you need a .edu or a .ac email address), not free for commercial use. Obtain your licence from
https://www.reversepoco.co.uk/
Other
707 stars 228 forks source link

Overriding Table Name does not override reverse navigation properties #599

Open MarkLFT opened 4 years ago

MarkLFT commented 4 years ago

I am probably going about thisa completely the wrong way. But, I need to rename several table/entity classes. In the legacy database, and in the code there are several tables for Accounts Receivable and Accounts Payable that are prefixed AR or AP. But the generator renames the classes to Ar and Ap, this little thing is causing huge problems.

Using the UpdateTable delegate/function onn the database.tt file I have renamed the HumanCase to be the uppercase AR and AP. But the Reverse Nagigation properties still use the Ar/Ap varients for both the class name and the property name. I have searched through the ttinclude file and the database.tt file, and I cannot see a straightforward way to to apply the same case changes to these properties.

Is there a simple way to apply some simple casing rules that will apply to all areas the table/column etc. names are used?

A sub note, I have found the SettingsForeignKeyName method, and I have used that to rename the name of the Reverse Nagigation, but the type is still wrong. I am current getting public virtual ArInvoice ARInvoice { get; set; }

But strangely when I debug the tt file in the Settings.ForeignKeyName, the table names are correctly cased.

Thanks for your help, and this is a great tool.

sjh37 commented 4 years ago

Hi Mark,

For changing the case of a table name, it's the last line that's causing it:

var tableName = filter.TableRename(tn.TableName, tn.SchemaName, tn.IsView);
var singularCleanTableName = Inflector.MakeSingular(DatabaseReader.CleanUp(tableName));
table.NameHumanCase = (Settings.UsePascalCase ? Inflector.ToTitleCase(singularCleanTableName) : singularCleanTableName).Replace(" ", "").Replace("$", "").Replace(".", "");

Try changing the code to:

var tableName = filter.TableRename(tn.TableName, tn.SchemaName, tn.IsView);
var singularCleanTableName = Inflector.MakeSingular(DatabaseReader.CleanUp(tableName));
if(tableName == tn.TableName)
    table.NameHumanCase = Settings.UsePascalCase ? Inflector.ToTitleCase(singularCleanTableName) : singularCleanTableName;
else
    table.NameHumanCase = singularCleanTableName;
table.NameHumanCase = table.NameHumanCase.Replace(" ", "").Replace("$", "").Replace(".", "");

See if that helps for the casing of table names.

MarkLFT commented 4 years ago

Firstly, apologies for the delay, we are in GMT+8 timezone.

I changed the code as you suggested, however on line 3728 tableName and tn.TableName are both already in the correct format i.e. AP???? or AR????? so it always uses the first option, which is to convert it to TitleCase thus changing what is correct to back to Ar and Ap.

I can see a dirty workaround here, by looking for the specific tables and applying the rules accorindingly. But I concerned about changign the code in the ttinclude file and more than is absolutely necessary, as at somepoint there wil be updates, and I will have to find all the changes, and re-implement them in the new ttinclude fie.

So I guess my question would be, is the searching for the specific table names and applying appropriate rules the best way forward?

Many thanks

MarkLFT commented 4 years ago

Just as a follow up. I tried to remove the table renaming in the Settings.UpdateTable delegate, and used the code you mentioned above, but looking for specific table names rather than just looking if the names are the same.

This renamed the table classes correctly, but the navigation properties are still not coming out correctly. The Parent class APTable contains the navigation property of

public virtual ICollection APCredit1 { get; set; } = new List();

Which is correct, except the property should be called APCrredits, not APCredit1.

And the Child class has a navigation proptery of

public virtual ApCredit APCredit { get; set; }

Where the class type should match the class and be APCredit, not ApCredit.

All other properties, classes etc are correct, it is just these pesky navigation properties that seem to have an issue.

MarkLFT commented 4 years ago

Sorry, me again. But this will be th elast post for a while. ;-)

By stepping through the code, line by line, I managed to find ttinclude lines 4310 and 4311 where the class names for navigation properties are set. So my adding extra rules in foreignKey.PKTableHumanCase() I have fixed the issue with the class name in the child class.

But I regret I cannot fathom how the plural name for the navigation property int he parent class is created? I really could do with some help here.

Many thanks.

sjh37 commented 4 years ago

Hi Mark,

Take a look at case 1 in the Settings.ForeignKeyName = delegate... callback in your <database>.tt file.

For a test, set all the fkNames to uppercase, to see what effect it has. Then if that adjusts your FK's you are interested in, write code to adjust the casing of your foreign keys.

 switch (attempt)
 {
     case 1: fkName = tableName.ToUpper();
...

The 5 attempts are there to try and not get a name clash. It goes from the best to worst name for the fk in order to get a unique name for it.

MarkLFT commented 4 years ago

Just to get back to you on this. I have soved the problem, it took a few little tweeks in several files to get what I needed. When I have a little more time, I will make a list of all the places I needed to make changes, just in case anyone else has this issue.