EF Core: Customizing the Name of Generated Models in Scaffolding

    It just so happened that in our old ASP.NET MVC project, database table models were stored with identical names, i.e. in lower case, with underscores, etc., and DTO is already in the .NET naming standard .


    This has been done for a number of reasons. The main ones: the scope of the model is explicitly set; convenience when building linq queries, when the names of tables and columns can be safely transferred from, for example, sql queries.


    Unfortunately, in .NET Core applications EDMX is no longer supported, and the CLI team has a rather meager set of features. Therefore, we had to go for a little trick.


    It is possible that this option will be added in release 1.2 , but so far it is not there, so you have to go to extreme, temporary measures.


    Step 1. Creating a project


    First, create a project that will contain all of our models. It will be a .NET Core console application.




    Why Console Application, and not Class library, you ask. The thing is that the Entity Framework supports the .NET Core CLI commands of only these frameworks:


    • .NET Framework 4.5.1 and newer. (“Net451”, “net452”, “net46”, etc.)
    • .NET Core App 1.0. (“Netcoreapp1.0”)

    And the Class library uses netstandard, not fate. In any case, the created console .NET Core application can be added to the ASP.NET Core project.


    Step 2. Configuring project.json


    I will not beat around the bush, to paint what this file is responsible for, I think there is no particular sense, we are not here for this.


    {
      "version": "1.0.0-*",
      "buildOptions": {
        "debugType": "portable",
        "emitEntryPoint": true
      },
      "dependencies": {
          "Microsoft.NETCore.App": {
            "type": "platform",
            "version": "1.0.0"
          },
          "Microsoft.EntityFrameworkCore.SqlServer": "1.0.0",
          "Microsoft.EntityFrameworkCore.SqlServer.Design": "1.0.0",
          "Microsoft.EntityFrameworkCore.Design": "1.0.0-preview2-final"
      },
      "frameworks": {
        "netcoreapp1.0": {
          "imports": "dnxcore50"
        }
      },
      "tools": {
        "Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final"
      }
    }

    Step 3. Configure injected dependencies


    When creating, our Program.cs looks something like this:


    namespace DomainModels
    {
        public class Program
        {
            public static void Main(string[] args)
            {
            }
        }
    }

    We will expand it. So, let's move on to a little research. After a bit of digging into the EF source code on GitHub, I discovered a dependency injection of the CandidateNamingService class during scaffolding. A quick glance at the code, I realized that it was responsible for converting the name of the database entity into the format of the standard .NET naming convention. And all that remains for us is to override the GenerateCandidateIdentifier function so that it returns the original name of the entity.


    Let's extend our code to this option:


    namespace DomainModels
    {
        public class Program
        {
            public static void Main(string[] args)
            {
            }
        }
        public class MyCandidateNamingService : CandidateNamingService
        {
            public override string GenerateCandidateIdentifier(string original)
            {
                return original;
            }
        }
    }

    Of course you can put any logic to taste in the GenerateCandidateIdentifier .


    Now you need to inject the dependency using AddSingleton. But where and how to do it? Since CandidateNamingService refers to design-time services, we need to define the ConfigureDesignTimeServices method in the Program class:


    namespace DomainModels
    {
        public class Program
        {
            public static void Main(string[] args)
            {
            }
            public void ConfigureDesignTimeServices(IServiceCollection services)
            {
                services.AddSingleton();
            }
        }
        public class MyCandidateNamingService : CandidateNamingService
        {
            public override string GenerateCandidateIdentifier(string original)
            {
                return original;
            }
        }
    }

    Done! It's time to do model generation.


    Step 4. Scaffolding


    Here I will not go into details, all CLI features are described here , and we will consider the final version of the commands without various settings:


    dotnet restore
    dotnet run
    dotnet ef dbcontext scaffold 'строка-соединения-с-бд' Microsoft.EntityFrameworkCore.SqlServer

    That's all that is needed to configure and generate models. By the way, for a more convenient scaffolding, I wrote a small PowerShell script , suddenly it will come in handy for someone.


    Also popular now: