How to singularize entities with EntityFramework core
Asked Answered
O

1

5

recently I've created an ASP.NET Core (Multiplatform) project and a ClassLibrary for Managing SQL Server Database models by using VS2017.

Actually we have a Database in production server and I need to generate classes by using dotnet ef dbcontext scaffold [arguments] [options] ... command line, however I need to singularize class name while creating DbContext class.

Please, need help! thanks

Olympiaolympiad answered 17/7, 2017 at 16:52 Comment(5)
I have never done this but I would be guessing you are going to need to update the T4 template file. It essentially is the instructions to write the files. It is the code that tells the code what to create for class files. If you update that it could be the equivalent of finding the loop that that goes through the tables and instead of creating a file for each, just append a class to a single file. Or you could create all the files and then create an after market application that then blends them in one file. Either way would suffice.Metathesize
can you tell me the path to T4 template file in VS2017, I've found path C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\ItemTemplates\CSharp\Data, however there are several folder into in where tt files have same namesOlympiaolympiad
Nothing that complex. When you create an Entity File(an edmx) file. You have a few levels to it. There is the file, the instructions( (name).context.tt and (name).tt), and the files created. You need to expand your edmx file and update the (name).tt file to get what you want. But you need to learn the T4 language a little bit. Be aware you can majorly mess up your existing code going this route so be careful and have a backup. You could make up a second T4 to run as well. Here is a link: msdn.microsoft.com/en-us/library/…Metathesize
I've found an alternative by implementing IDesignTimeServices as explained in romiller.com/2017/02/10/…, however, is not well explained how to use with Scaffold-DbContext nor dotnet ef dbcontext ...commands. Anybody knows which parameter works for this kind of implementation?Olympiaolympiad
Straightforward article meziantou.net/2017/06/26/…Recreation
O
13

I've found the solution!

The best solution is to implement the IDesignTimeServices interface and use the inflector tool as explained in https://romiller.com/2017/02/10/ef-core-1-1-pluralization-in-reverse-engineer/.

To put in action such solution, DesignTimeService, DbContextWriter, ModelConfiguration, RelationalScaffoldingModelFactory custom classes and Inflector class must reside in startup project where Startup Class is located. Execute following commands by using package manager console:

Install-Package Microsoft.EntityFrameworkCore.Design 

and

Install-Package Microsoft.EntityFrameworkCore.Tools

During Scaffold process, Entity Framework Design searches for any class that implements IDesignTimeServices into Startup project and its code is executed.

Execute the following command replacing values as needed by using package manager console keeping in mind that if it is required to store models classes in a Database First process into other project (f.e. Class Library), select it previously in Visual Studio Package Manager Console:

Scaffold-DbContext -provider Microsoft.EntityFrameworkCore.SqlServer -connection "<connection string here...>" -Context MyDbContext -OutputDir "folder path" -StartupProject MyMainProject -Force

That's all, singularization and any customization needed works perfect!

Thanks for help provided in the comments!

UPDATE:

Recent Entity Framework Core 2.0 version has improved the Singularization/Pluralization process avoiding the requirement of DbContextWriter, ModelConfiguration and RelationalScaffoldingModelFactory implementation, making this process simpler through a new interface named IPluralizer which you use in a class that implements the methods Pluralize and Singularize.

Same packages installation of Microsoft.EntityFrameworkCore.Design, Microsoft.EntityFrameworkCore.Tools are required, also Microsoft.EntityFrameworkCore.SqlServer if you want this DataBase in your solution, but now the class that implements IDesignTimeServices only requires the class implementing IPluralizer in a simpley way as:

public class CustomDesignTimeService : IDesignTimeServices
{
    public void ConfigureDesignTimeServices(IServiceCollection serviceCollection)
                => serviceCollection.AddSingleton<IPluralizer, CustomPluralizer>();
}

Finally, CustomPluralizer just uses Inflector tool class methods:

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

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

Just implement your own Pluralize/Singularize code if you don't want to use Inflector class.

That's all what I had to do in my new ASP.NET Core 2.0 project. I hope this help!

Olympiaolympiad answered 18/7, 2017 at 20:28 Comment(6)
This should be the default behavior of entity framework core, or at least be an option on the Scaffold-DbContext command ( -pluralize? )Obscenity
also the Inflector does not work with .NET Core. You have to copy the code into your project from raw.githubusercontent.com/markrendle/Inflector/master/Inflector/…Inositol
Yes, copying the source code into new class file works perfect in .net core.Olympiaolympiad
I'm curious, why is the Singularize method used instead of Pluralize? I haven't specifically told it to use Singularize, just provided an implementation for itNacred
The main reason to run Singularize instead of Pluralize is because of the tables name are pluralized so when you are running a scaffolding command, it doesn't make sense to run a Pluralize. However, Pluralize makes sense when you need to run a code first.Olympiaolympiad
If you are using efcore >= 3 and IPluralizer cannot be found, check out: https://mcmap.net/q/1923168/-where-to-find-ipluralizerHypnotism

© 2022 - 2024 — McMap. All rights reserved.