Сущности EF Core Scaffold с интерфейсом

Я использую основные инструменты Entity Framework для создания сущностей. и DBContext из существующей базы данных.

Scaffold-DbContext "Server=XXXXXX;Database=MyDB;User ID=xxxx;Password=xxxxxxx" Microsoft.EntityFrameworkCore.SqlServer -ContextDir .-OutputDir Entities -Force

Это работает. Но есть ли способ собрать все сущности с известным интерфейсом? Итак, у меня есть интерфейс IEntityBase, и я хочу, чтобы все объекты имели этот интерфейс.

Примечание. Этот вопрос относится к EF Core 2+ и скаффолдингу.

Обновление 1
Итак, согласно SO Suggesion я создал CSharpEntityTypeGenerator и IDesignTimeServices Принятый ответ недействителен для EF Core > 2.*, поэтому я использую предложение @Chris Peacock

public class MyEntityTypeGenerator: CSharpEntityTypeGenerator
{
    public MyEntityTypeGenerator(ICSharpHelper cSharpHelper)
        : base(cSharpHelper)
    {
    }

    public override string WriteCode(IEntityType entityType, string @namespace, bool useDataAnnotations)
    {
        string code = base.WriteCode(entityType, @namespace, useDataAnnotations);

        var oldString = "public partial class " + entityType.Name;
        var newString = "public partial class " + entityType.Name + " : EntityBase";

        return code.Replace(oldString, newString);
    }
}


public class MyDesignTimeServices: IDesignTimeServices
{
    public void ConfigureDesignTimeServices(IServiceCollection serviceCollection)
    {
        serviceCollection.AddSingleton<ICSharpEntityTypeGenerator, MyEntityTypeGenerator>();
    }
}

Есть одно изменение, которое я должен был сделать. Конструктор CSharpEntityTypeGenerator принимает в качестве параметра ICSharpHelper вместо ICSharpUtilities

Эти два класса находятся в сборке Data, которая не является стартовым проектом.

В консоли диспетчера пакетов я снова выполнил команду создания лесов. Однако я не вижу, чтобы сгенерированные объекты имели базовый класс.

Как инфраструктура строительных лесов узнает, что нужно использовать мой пользовательский генератор? Я добавляю генератор в serviceCollection, но похоже, что код никогда не выполняется

Я что-то упускаю?


person LP13    schedule 05.06.2019    source источник
comment
@AdamVincent это не дубликат. Мой вопрос связан с ядром .net и специфичен для Scaffolding с использованием инструментов EF Core. По крайней мере, это не то же самое, что вы связали   -  person LP13    schedule 06.06.2019
comment
Просто для ясности: вы хотите, чтобы операция создания лесов добавляла .. : IEntityBase ко всем вашим классам, созданным из базы данных?   -  person Adam Vincent    schedule 06.06.2019
comment
Возможный дубликат Entity Framework Core Customize Scaffolding   -  person Jan Paolo Go    schedule 06.06.2019
comment
@AdamVincent да, но .net.core использует EF Core   -  person LP13    schedule 06.06.2019


Ответы (2)


Для этого можно использовать шаблоны EF Core Power Tools with Handlebars.

https://github.com/ErikEJ/EFCorePowerTools/wiki/Reverse-Engineering#customize-code-using-handlebars

person ErikEJ    schedule 06.06.2019
comment
Я скачал Power Tool, но он не поддерживает добавление базового класса/интерфейса из коробки. Как вы упомянули, я должен использовать руль. Я решил придерживаться подхода С# :). Мне пришлось бы использовать инструмент питания, если бы он просто предоставлял текстовое поле для ввода имени базового класса или интерфейса. Для более сложной настройки можно использовать рули. - person LP13; 06.06.2019

Я думаю, что эти параметры должны были быть предоставлены как часть инструмента EF Scaffolding по умолчанию.

Но вот мой код. Я использую Microsoft.EntityFrameworkCore.Design 2.2.4 и Microsoft.EntityFrameworkCore.SqlServer 2.2.4, и исходя из моего опыта работы с .NET Core, это может измениться в будущей версии.

CSharpEntityTypeGenerator

public class MyEntityTypeGenerator: CSharpEntityTypeGenerator
{
    public MyEntityTypeGenerator(ICSharpHelper cSharpUtilities)
        : base(cSharpUtilities)
    {
    }

    public override string WriteCode(IEntityType entityType, string @namespace, bool useDataAnnotations)
    {
        Console.WriteLine(entityType.Name);

        string code = base.WriteCode(entityType, @namespace, useDataAnnotations);

        var oldString = "public partial class " + entityType.Name;
        var newString = "public partial class " + entityType.Name + " : EntityBase";

        return code.Replace(oldString, newString);
    }
}

По умолчанию скаффолдинг создает классы с тем же именем, что и имя таблицы. В нашем случае имена таблиц Pluralize, но нам нужно имя класса Singularize. Итак, вы должны реализовать Microsoft.EntityFrameworkCore.Design.IPluralizer. Я использовал утилиту Inflator. Однако обратите внимание, что я не смог добавить Inflector с помощью Nuget в проекте .Net Core. Похоже, он еще не поддерживает .NET Core. Поэтому я добавил один файл кода вместо этого в свой проект. .

IPluralizer

public class MyPluralizer : IPluralizer
{
    public string Pluralize(string identifier)
    {
        return Inflector.Pluralize(identifier) ?? identifier;
    }

    public string Singularize(string identifier)
    {
        return Inflector.Singularize(identifier) ?? identifier;
    }
}

IDesignTimeServices
Вам необходимо добавить этот класс в стартовый проект. Изначально у меня был этот класс в том же проекте, что и другие классы, но это не сработало. Я переместил этот класс в стартовый проект (в моем случае это проект ASP.NET Core), и он сработал.

public class MyDesignTimeServices : IDesignTimeServices
{
    public void ConfigureDesignTimeServices(IServiceCollection serviceCollection)
    {
        // Start debugger
        System.Diagnostics.Debugger.Launch();
        serviceCollection.AddSingleton<ICSharpEntityTypeGenerator, MyEntityTypeGenerator>();
        serviceCollection.AddSingleton<IPluralizer, MyPluralizer>();
    }
}
person LP13    schedule 06.06.2019
comment
Для информации, в EFCore 3 произошли изменения во множественном числе, я только что посмотрел на это сам, но следующая ссылка может быть полезна людям - github.com/dotnet/efcore/issues/17401 - person d219; 09.01.2020
comment
Особенно вам нужно добавить этот класс в стартовый проект. Изначально у меня был этот класс в том же проекте, что и другие классы, но это не сработало. Я переместил этот класс в проект запуска (в моем случае это проект ASP.NET Core), и он работал и у меня. - person Mustafa; 10.04.2020