Pull to refresh

EF Core: Настройка имени генерируемых моделей в Scaffolding

Reading time 3 min
Views 3.7K

Так уж вышло, что в нашем старом ASP.NET MVC проекте модели таблиц базы данных хранились с идентичными именами, т.е. в нижнем регистре, с подчеркиваниями и пр., а DTO уже в стандарте именования .NET.


Это было сделано по ряду причин. Основные из них: явно задана область применения модели; удобство при построении linq запросов, когда названия таблиц и столбцов можно спокойно переносить из, к примеру, sql запроса.


К сожалению в .NET Core приложениях EDMX больше не поддерживается, а в CLI команде достаточно скудный набор возможностей. Поэтому нам пришлось пойти на небольшую хитрость.


Возможно, в релизе 1.2 добавят эту опцию, но пока ее нет, так что придется идти на крайние, временные меры.


Шаг 1. Создание проекта


Для начала создадим проект, который будет содержать все наши модели. Это будет консольное приложение .NET Core.




Почему именно Console Application, а не Class library спросите Вы. Все дело в том Entity Framework поддерживает .NET Core CLI команды только этих фреймворков:


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

А Class library использует netstandard, не судьба. В любом случае созданное консольное .NET Core приложение можно добавить в ASP.NET Core проект.


Шаг 2. Настройка project.json


Не буду ходить вокруг да около, расписывать за что отвечает данный файл я думаю смысла особого нет, мы не для этого тут собрались.


{
  "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"
  }
}

Шаг 3. Настройка внедряемых зависимостей


При создании наш Program.cs выглядит примерно так:


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

Его мы и будем расширять. Так, перейдем к небольшому исследованию. Немного покопавшись в исходниках EF на GitHub я обнаружил внедрение зависимости класса CandidateNamingService при scaffolding. Пробежав беглым взглядом код, я понял, что он отвечает за преобразование имени сущности базы данных в формат стандарта .NET именования. И все, что нам осталось, это переопределить функцию GenerateCandidateIdentifier, чтобы она возвращала оригинальное имя сущности.


Давайте расширим наш код до такого варианта:


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

    public class MyCandidateNamingService : CandidateNamingService
    {
        public override string GenerateCandidateIdentifier(string original)
        {
            return original;
        }
    }
}

Само собой вы можете поместить любую логику по вкусу в GenerateCandidateIdentifier.


Теперь необходимо внедрить зависимость с помощью AddSingleton. Но где и как это сделать? Так как CandidateNamingService относится к design-time сервисам нам необходимо определить метод ConfigureDesignTimeServices в классе Program:


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

        public void ConfigureDesignTimeServices(IServiceCollection services)
        {
            services.AddSingleton<CandidateNamingService, MyCandidateNamingService>();
        }
    }

    public class MyCandidateNamingService : CandidateNamingService
    {
        public override string GenerateCandidateIdentifier(string original)
        {
            return original;
        }
    }
}

Готово! Пора выполнять генерацию моделей.


Шаг 4. Scaffolding


Тут я не буду вдаваться в подробности, все особенности CLI расписаны тут, а мы рассмотрим итоговый вариант команд без различных настроек:


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

Вот собственно и все, что нужно для настройки и генерации моделей. Кстати, для более удобного scaffolding я написал небольшой PowerShell скрипт, вдруг кому-то пригодится.

Tags:
Hubs:
+10
Comments 0
Comments Leave a comment

Articles