Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EF Core - Navigation Properties naming in scaffolding

For a really big client I need to create a new architecture and the processes to develop that architecture. I need to use a Database first Strategy and scaffolding from database for every modification.

But the scafolding names for one to one navigation properties are really confusing because it uses the column name instead of the table related.

I have a foreign key in the Invoice table to the product table. The column name IdProduct will give a navigation property named IdProductNavigation

    public Product IdProductNavigation { get; set; }

I understand that it may have been done this way because there can be multiple foreign keys to the same table. In Ef 6 or before the navigation properties were named Products and then Products_1, Products_2, ...

Please can someone tell me How can I give a name to this navigation Property ? I cannot rename the columns but Is there a way to configure the scafolding or maybe to comments the columns or the foreign keys in the database to modify the scaffolding ?

Thank you for your time

like image 281
neothoms Avatar asked May 31 '18 09:05

neothoms


People also ask

What is navigation property in Entity Framework Core?

Navigation property: A property defined on the principal and/or dependent entity that references the related entity. Collection navigation property: A navigation property that contains references to many related entities.

What is navigation property in entity data model?

A navigation property is an optional property on an entity type that allows for navigation from one end of an association to the other end. Unlike other properties, navigation properties do not carry data.

What is Scaffold-DbContext command?

The above Scaffold-DbContext command creates entity classes for each table in the SchoolDB database and context class (by deriving DbContext ) with Fluent API configurations for all the entities in the Models folder. The following is the generated Student entity class for the Student table.


1 Answers

You can personalize the naming of the Navigation Properties adding your own Service to the scaffold.

Create a class in the Startup Project of your scaffold that extends IDesignTimeServices and a Service for ICandidateNamingService. Example: MyEFDesignTimeServices.cs

using Microsoft.EntityFrameworkCore.Design;
using Microsoft.EntityFrameworkCore.Scaffolding.Internal;
using Microsoft.Extensions.DependencyInjection;
using StartProject;
using System;
using System.Collections.Generic;
using System.Text;

public class MyEFDesignTimeServices : IDesignTimeServices
{
    public void ConfigureDesignTimeServices(IServiceCollection serviceCollection)
    {
        serviceCollection.AddSingleton<ICandidateNamingService, CustomCandidateNamingService>();
    }
}

Now create the CustomCandidateNamingService.cs class by extending CandidateNamingService In my example, I decided to use the DefaultName of the ForeignKey with in my case (SQL Server) is always FK_TableA_TableB_Field1_Field2, so I delete the FK_ and the Table Name of the actual Table.

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Scaffolding.Internal;
using System;
using System.Collections.Generic;
using System.Text;

namespace StartProject
{
    public class CustomCandidateNamingService: CandidateNamingService
    {
        public override string GetDependentEndCandidateNavigationPropertyName(IForeignKey foreignKey)
        {
            try
            {
                string newName = foreignKey.GetDefaultName().Replace("FK_", "")
                                           .Replace(foreignKey.DeclaringEntityType.Name + "_", "", StringComparison.OrdinalIgnoreCase);
                return newName;
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error in Generating GetDependentEndCandidateNavigationPropertyName: " + ex.Message);
            }

            return base.GetDependentEndCandidateNavigationPropertyName(foreignKey);
        }

        public override string GetPrincipalEndCandidateNavigationPropertyName(IForeignKey foreignKey, string dependentEndNavigationPropertyName)
        {
            try
            {
                string newName = foreignKey.GetDefaultName().Replace("FK_", "")
                                           .Replace(foreignKey.PrincipalEntityType.Name + "_", "", StringComparison.OrdinalIgnoreCase);
                return newName;
            }
            catch(Exception ex) {
                Console.WriteLine("Error in Generating GetPrincipalEndCandidateNavigationPropertyName: " + ex.Message);
            }
            return base.GetPrincipalEndCandidateNavigationPropertyName(foreignKey, dependentEndNavigationPropertyName);
        }


    }
}

Attention: I use the Microsoft.EntityFrameworkCore.Scaffolding.Internal Internal API. This can change in the future without notice.

like image 141
erbg Avatar answered Dec 02 '22 03:12

erbg