R4ND3LL / EntityFrameworkRuler

Automate the customization of the Entity Framework Reverse Engineered model, including EDMX support for EF6 upgrades.
MIT License
20 stars 5 forks source link

Entities not picking up new names #26

Closed jdanielpa closed 1 year ago

jdanielpa commented 1 year ago

Hey Mark,

I am back working with your tool - I am using version 1.2.27. I have several tables in SQL that have names that end with 'Data'. These are being translated to 'Datum' I have confirmed in my EDMX everything is 'Data' and as you can see in the image below the Ruler shows the new name will be 'Data' but I still get Datum:

image

Can you tell me what I am doing wrong? I made sure to install the latest VS Extension plugin as well.

Thanks, Jason

jdanielpa commented 1 year ago

I might have been premature on this issue. I discovered the EDMX project was not building. I fixed the issue but it exposed a new problem.

I have an class inheritance that is: PlasticData : ToolData ToolData : PartDesignData

When I scaffold, I get: RULED: Corrected navigation Design.PartDesignDatasNavigation name to 'PartDesignDatas' RULED: Foreign key FK_LensData_PartDesignData omitted. RULED: Foreign key FK_ToolData_PartDesignData omitted. RULED: Foreign key FK_PlasticData_ToolData omitted. System.InvalidOperationException: The navigation 'PlasticData (Dictionary<string, object>).PartNavigation' cannot be associated with foreign key {'PartID'} because it was created for foreign key {'PartID'}. at Microsoft.EntityFrameworkCore.Metadata.Internal.EntityType.AddNavigation(MemberIdentity navigationMember, ForeignKey foreignKey, Boolean pointsToPrincipal) at Microsoft.EntityFrameworkCore.Metadata.Internal.ForeignKey.Navigation(Nullable1 propertyIdentity, ConfigurationSource configurationSource, Boolean pointsToPrincipal) at Microsoft.EntityFrameworkCore.Metadata.Internal.ForeignKey.SetDependentToPrincipal(String name, ConfigurationSource configurationSource) at Microsoft.EntityFrameworkCore.Metadata.Internal.ForeignKey.Microsoft.EntityFrameworkCore.Metadata.IMutableForeignKey.SetDependentToPrincipal(String name) at Microsoft.EntityFrameworkCore.Scaffolding.Internal.RelationalScaffoldingModelFactory.AddNavigationProperties(IMutableForeignKey foreignKey) at Castle.Proxies.RelationalScaffoldingModelFactoryProxy.AddNavigationProperties_callback(IMutableForeignKey foreignKey) at Castle.Proxies.Invocations.RelationalScaffoldingModelFactory_AddNavigationProperties.InvokeMethodOnTarget() at Castle.DynamicProxy.AbstractInvocation.Proceed() at EntityFrameworkRuler.Design.Services.RuledRelationalScaffoldingModelFactory.<>cDisplayClass57_0.gBaseCall|0(IMutableForeignKey fk1) at EntityFrameworkRuler.Design.Services.RuledRelationalScaffoldingModelFactory.AddNavigationProperties(IMutableForeignKey foreignKey, Action1 baseCall) at EntityFrameworkRuler.Design.Services.RuledRelationalScaffoldingModelFactory.Castle.DynamicProxy.IInterceptor.Intercept(IInvocation invocation) at Castle.DynamicProxy.AbstractInvocation.Proceed() at Castle.Proxies.RelationalScaffoldingModelFactoryProxy.AddNavigationProperties(IMutableForeignKey foreignKey) at Microsoft.EntityFrameworkCore.Scaffolding.Internal.RelationalScaffoldingModelFactory.VisitForeignKeys(ModelBuilder modelBuilder, IList1 foreignKeys) at Castle.Proxies.RelationalScaffoldingModelFactoryProxy.VisitForeignKeys_callback(ModelBuilder modelBuilder, IList`1 foreignKeys) at Castle.Proxies.Invocations.RelationalScaffoldingModelFactory_VisitForeignKeys.InvokeMethodOnTarget() at Castle.DynamicProxy.AbstractInvocation.Proceed() at EntityFrameworkRuler.Design.Services.RuledRelationalScaffoldingModelFactory.<>cDisplayClass57_0.gBaseCall|5(IList1 databaseForeignKeys) at EntityFrameworkRuler.Design.Services.RuledRelationalScaffoldingModelFactory.VisitForeignKeys(ModelBuilder modelBuilder, IList1 foreignKeys, Func2 baseCall) at EntityFrameworkRuler.Design.Services.RuledRelationalScaffoldingModelFactory.Castle.DynamicProxy.IInterceptor.Intercept(IInvocation invocation) at Castle.DynamicProxy.AbstractInvocation.Proceed() at Castle.Proxies.RelationalScaffoldingModelFactoryProxy.VisitForeignKeys(ModelBuilder modelBuilder, IList1 foreignKeys) at Microsoft.EntityFrameworkCore.Scaffolding.Internal.RelationalScaffoldingModelFactory.VisitDatabaseModel(ModelBuilder modelBuilder, DatabaseModel databaseModel) at Castle.Proxies.RelationalScaffoldingModelFactoryProxy.VisitDatabaseModel_callback(ModelBuilder modelBuilder, DatabaseModel databaseModel) at Castle.Proxies.Invocations.RelationalScaffoldingModelFactory_VisitDatabaseModel.InvokeMethodOnTarget() at Castle.DynamicProxy.AbstractInvocation.Proceed() at EntityFrameworkRuler.Design.Services.RuledRelationalScaffoldingModelFactory.<>cDisplayClass57_0.gBaseCall|2() at EntityFrameworkRuler.Design.Services.RuledRelationalScaffoldingModelFactory.VisitDatabaseModel(ModelBuilder modelBuilder, DatabaseModel databaseModel, Func`1 baseCall) at EntityFrameworkRuler.Design.Services.RuledRelationalScaffoldingModelFactory.Castle.DynamicProxy.IInterceptor.Intercept(IInvocation invocation) at Castle.DynamicProxy.AbstractInvocation.Proceed() at Castle.Proxies.RelationalScaffoldingModelFactoryProxy.VisitDatabaseModel(ModelBuilder modelBuilder, DatabaseModel databaseModel) at Microsoft.EntityFrameworkCore.Scaffolding.Internal.RelationalScaffoldingModelFactory.Create(DatabaseModel databaseModel, ModelReverseEngineerOptions options) at Castle.Proxies.RelationalScaffoldingModelFactoryProxy.Create_callback(DatabaseModel databaseModel, ModelReverseEngineerOptions options) at Castle.Proxies.Invocations.RelationalScaffoldingModelFactory_Create.InvokeMethodOnTarget() at Castle.DynamicProxy.AbstractInvocation.Proceed() at EntityFrameworkRuler.Design.Services.RuledRelationalScaffoldingModelFactory.<>cDisplayClass57_0.gBaseCall|7(DatabaseModel databaseModel, ModelReverseEngineerOptions options2) at EntityFrameworkRuler.Design.Services.RuledRelationalScaffoldingModelFactory.Create(DatabaseModel databaseModel, ModelReverseEngineerOptions ops, Func3 baseCall) at EntityFrameworkRuler.Design.Services.RuledRelationalScaffoldingModelFactory.Castle.DynamicProxy.IInterceptor.Intercept(IInvocation invocation) at Castle.DynamicProxy.AbstractInvocation.Proceed() at Castle.Proxies.RelationalScaffoldingModelFactoryProxy.Create(DatabaseModel databaseModel, ModelReverseEngineerOptions options) at EntityFrameworkRuler.Design.Services.RuledRelationalScaffoldingModelFactory.Create(DatabaseModel databaseModel, ModelReverseEngineerOptions ops) at Microsoft.EntityFrameworkCore.Scaffolding.Internal.ReverseEngineerScaffolder.ScaffoldModel(String connectionString, DatabaseModelFactoryOptions databaseOptions, ModelReverseEngineerOptions modelOptions, ModelCodeGenerationOptions codeOptions) at EntityFrameworkRuler.Design.Services.RuledReverseEngineerScaffolder.ScaffoldModel(String connectionString, DatabaseModelFactoryOptions databaseOptions, ModelReverseEngineerOptions modelOptions, ModelCodeGenerationOptions codeOptions) at Microsoft.EntityFrameworkCore.Design.Internal.DatabaseOperations.ScaffoldContext(String provider, String connectionString, String outputDir, String outputContextDir, String dbContextClassName, IEnumerable1 schemas, IEnumerable1 tables, String modelNamespace, String contextNamespace, Boolean useDataAnnotations, Boolean overwriteFiles, Boolean useDatabaseNames, Boolean suppressOnConfiguring, Boolean noPluralize) at Microsoft.EntityFrameworkCore.Design.OperationExecutor.ScaffoldContextImpl(String provider, String connectionString, String outputDir, String outputDbContextDir, String dbContextClassName, IEnumerable1 schemaFilters, IEnumerable1 tableFilters, String modelNamespace, String contextNamespace, Boolean useDataAnnotations, Boolean overwriteFiles, Boolean useDatabaseNames, Boolean suppressOnConfiguring, Boolean noPluralize) at Microsoft.EntityFrameworkCore.Design.OperationExecutor.ScaffoldContext.<>c__DisplayClass0_0.<.ctor>b__0() at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_01.b__0() at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action) The navigation 'PlasticData (Dictionary<string, object>).PartNavigation' cannot be associated with foreign key {'PartID'} because it was created for foreign key {'PartID'}.

Is there an issue with the inheritance? The EDMX is fine with it.

Here is the edmx: image

Here is SQL: image

jdanielpa commented 1 year ago

I think I am close but I have the two entities that are erroring in the context (LensData and ToolData). Both with the same error. These both have the base class PartDesignData. Also, I have to exclude PlasticData for now otherwise the scaffolding fails. PlasticData has a base class of ToolData. I think the first issue is a template issue for my context?

Thoughts?

image

The error is: image

R4ND3LL commented 1 year ago

This is because EF Core is attempting to add the relationships from the TPT concrete types to the base types, which should not be present in an inheritance scenario.

This is because the 1:1 FKs exist in the DB, and are not properly excluded from the EFR json rules.

Normally, in the TPT mapping in the EDMX, the leaf type primary keys are set to map to the base type's primary key. See this link for details: https://leftlobed.wordpress.com/2011/03/02/getting-to-know-entity-framework-table-per-type-tpt-inheritance/

When the json rules are generated from this configuration, the leaf type's primary keys would naturally be marked as NotMapped, which would bypass the navigation mapping by EF Core.. However, in your EDMX, you have the leaf type primary keys deleted, and they are subsequently missing in the json rules.

I can probably add code to catch this case during scaffolding, however, as a work around you can simply ensure the leaf types have the primary keys listed and marked as not mapped. For example:

{ "Name": "ToolData", "EntityName": "ToolDatum", "NewName": "ToolData", "BaseTypeName": "PartDesignData", "IncludeUnknownColumns": false, "Properties": [ { "Name": null, "NewName": "PartIDTool", "NotMapped": true }, ... ],

jdanielpa commented 1 year ago

OK. I made those changes but after scaffolding I still get:

@.***

I also get it on the ToolData and I still have to set PlasticData to NotMapped or I still get the scaffolding error.

Would it be better and/or Is there a way for me to fix it in the EDMX? I thought you had to delete the PK from the entity and set its base type to PartDesignData?

Thanks, Jason

R4ND3LL commented 1 year ago

Issue of entities involved in inheritance receiving unexpected navigation property names has been resolved in EFR Design package v1.2.36.

FKs/Navigations between entities in TPT hierarchy are now correctly ignored (automatically) in the above revision also.