Entity Framework Core Customize Scaffolding

落爺英雄遲暮 提交于 2019-12-01 04:12:59

You can use DbContextWriter & EntityTypeWriter to customize scaffold output.

In newer versions of entity core writers renamed:

  • DBContextWriter ==>> CSharpDbContextGenerator
  • EntityTypeWriter ==>> CSharpEntityTypeGenerator

Write some custom type writer, you can override everything and you will get your own code generator:

//HERE YOU CAN CHANGE THE WAY TYPES ARE GENERATED AND YOU CAN ADD INTERFACE OR BASE CLASS AS PARENT.
public class CustomEntitiyTypeWriter : EntityTypeWriter
{
    public CustomEntitiyTypeWriter([NotNull] CSharpUtilities cSharpUtilities)
        : base(cSharpUtilities)
    { }

    // Write Code returns generated code for class and you can raplec it with your base class
    public override string WriteCode([NotNull] EntityConfiguration entityConfiguration)
    {
        var classStr = base.WriteCode(entityConfiguration);

        var defaultStr = "public partial class " + entityConfiguration.EntityType.Name;
        var baseStr = "public partial class " + entityConfiguration.EntityType.Name + " : EntityBase";

        classStr = classStr.Replace(defaultStr, baseStr);

        return classStr;
    }      
}

declare it in setup:

public static void ConfigureDesignTimeServices(IServiceCollection services)
           => services.AddSingleton<EntityTypeWriter, CustomEntitiyTypeWriter>();

and then scaffold db, you can do the same for DBContext with CustomDBContextWriter.

@Tornike Choladze's excellent answer led me in the right direction, but in the latest versions of .Net Core (2.0 >) this has to be done a little differently it seems, with regard to the setup.

The custom entity type generator:

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

    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);
    }
}

And the setup, which consists of a class in the same assembly and implementing IDesignTimeServices:

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

Currently, the scaffolding tools do not support the scenario you describe. There are no options to customise their output, only the location of the generated files and whether to use Fluent API or data annotations for configuration.

EF Core is a Code First framework. The advice is that once you have reverse-engineered your model from the existing database, you use migrations to keep the two in sync with each other from then on.

Having said that, I realise that might not always be possible depending on how responsibilities are apportioned within teams. In that kind of case, you might want to consider opening an issue requesting this feature on the GitHub repo for EF Core: https://github.com/aspnet/EntityFramework.

In case you want to modify entity names (and file and class names) here's something that might help:

Based on Chris Peacock's answer (and comments) you can build two classes to modify the names of entities and files (this works in Core 2.2).

public class CustomEFUtilities : CSharpUtilities
{
    public override string Uniquifier(
        string proposedIdentifier, ICollection<string> existingIdentifiers)
    {
        var finalIdentifier = base.Uniquifier(proposedIdentifier, existingIdentifiers);

        // your changes here
        if (finalIdentifier.StartsWith("tl"))
        {
            finalIdentifier = finalIdentifier.Substring(2);
        }

        return finalIdentifier;
    }
}

And similarly:

public class CustomEFDesignTimeServices : IDesignTimeServices
{
    public void ConfigureDesignTimeServices(IServiceCollection serviceCollection)
    {
        serviceCollection.AddSingleton<ICSharpUtilities, CustomEFUtilities>();
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!