Skip to content

Extend Scaffold-DbContext to create separate EntityTypeBuilders #16911

@Krm1t

Description

@Krm1t

First off, I have been stuck at the Framework version of EntityFramework - Because of reasons :)
But I recently got to reverse engineer one of our databases for a new sub-project and so far i have liked working with EFCore.

There was however 1 thing about using "Scaffold-DbContext" that I would suggest changing.
The generated Context file can become rather large and annoying to maintain if the database being reverse engineered contains many tables.

Therefore i suggest that "Scaffold-DbContext" creates a sub-folder called something like "EntityTypeBuilders" and inside, an EntityTypeBuilder is generated for each entity (see code example below)
This can be done either by default or by using a flag with "Scaffold-DbContext" for backwards compatibility.
I omitted the actyal types from the example to make the code as short as possible.

namespace MyDataProject.Models.EntityTypeBuilders {
  internal static class MyTypeBuilder {
    public static ModelBuilder SetupMyType(this ModelBuilder builder)
    {
      builder.Entity<MyType>(entity =>
      {
        entity
        .SetupIndexes()
        .SetupProperties()
        .SetupRelationships();
      });

      return builder;
    }

    private static EntityTypeBuilder<MyType> SetupIndexes(this EntityTypeBuilder<MyType> entity)
    {
      entity.HasKey(e => e.Id).HasName("PK_MyType");
      entity.HasIndex(e => e.MyOtherTypeId).HasName("MyOtherTypeId_FK");
      return entity;
    }

    private static EntityTypeBuilder<MyType> SetupProperties(this EntityTypeBuilder<MyType> entity)
    {
      entity
        .Property(e => e.Id)
        .ValueGeneratedNever();
      entity
        .Property(e => e.Name)
        .HasMaxLength(255);

      return entity;
    }

    private static EntityTypeBuilder<MyType> SetupRelationships(this EntityTypeBuilder<MyType> entity)
    {
      entity
        .HasOne(d => d.MyOtherType)
        .WithMany(p => p.MyType)
        .HasForeignKey(d => d.MyOtherTypeId)
        .HasConstraintName("FK_MyOtherTypeId");
      return entity;
    }
  }
}

And in Context.OnModelCreating we would have the following code:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
  modelBuilder
    .SetupMyType()
    .SetupMyOtherType();
}

This way if you need to see/change the setup for MyType you just have to find the Builder for it and it will contain only the setup for that entity.

Obviously the current solution works. This change will just make it a little less overwhelming when working with large databases.

Further technical details

EF Core version: netcoreapp2.2
Database Provider: Microsoft.EntityFrameworkCore.SqlServer
Operating system: Windows 10
IDE: Visual Studio 2019 16.1.6

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions