Exclude tables when using Entity Framework Core Reverse Engineering

Exclude tables when using Entity Framework Core Reverse Engineering

Right now (October 2020) there is not an easy way to exclude tables when you Reverse Engineer your database (Database First).

There are two main ways to do it:

  1. Using Scaffold-DbContext and providing -table arguments. That means you should have a place where you will save all your tables. And everytime you want to add another one, you will have to update that list.
  2. Using EF CorePower Tools. The tool will allow you to select which tables you want to Reverse Engineer and save the selection for later.

Personally, I couldn't use EF Core Power Tools so I had to stick with the first option but since I'm working on an application for which new tables are created  regularly, I decided to make my own way of excluding tables.

As you probably already know, there is a way to modify how some design-time services are configured by implementing IDesignTimeServices inteface. That will allow us to modify the code which reads our database and decide which tables will used when reverse engineering. Go take a look by yourself on this file in the EF Core's repository.

The code will scan the database and will pick up all the tables taking also into consideration all the -table arguments if provided.

I decided that I want to decorate this service so I created a class named CustomSqlServerDatabaseModelFactory which will implement IDatabaseModelFactory in which I exclude 2 tables: __MigrationHistory and Exceptions. I'll paste the code here:

public class CustomSqlServerDatabaseModelFactory : IDatabaseModelFactory
{
    private IDatabaseModelFactory databaseModelFactory;

    private static readonly List<string> ExcludedTables = new List<string>
    {
      "__MigrationHistory",
      "Exceptions"
    };

    public CustomSqlServerDatabaseModelFactory(IDatabaseModelFactory databaseModelFactory)
    {
      this.databaseModelFactory = databaseModelFactory;
    }

    public DatabaseModel Create(string connectionString, DatabaseModelFactoryOptions options)
    {
      var databaseModel = databaseModelFactory.Create(connectionString, options);

      RemoveTables(databaseModel);

      return databaseModel;
    }

    public DatabaseModel Create(DbConnection connection, DatabaseModelFactoryOptions options)
    {
      var databaseModel = databaseModelFactory.Create(connection, options);

      RemoveTables(databaseModel);

      return databaseModel;
    }

    private static void RemoveTables(DatabaseModel databaseModel)
    {
      var tablesToBeRemoved = databaseModel.Tables.Where(x => ExcludedTables.Contains(x.Name)).ToList();

      foreach (var tableToRemove in tablesToBeRemoved)
      {
        databaseModel.Tables.Remove(tableToRemove);
      }
    }
}

Since Microsoft.Extensions.DependencyInjection does not allow us to register a decorator, I've decided to use a NuGet Package called Scrutor which allows me to do that pretty quickly.

public class CustomEFDesignTimeServices : IDesignTimeServices
{
    public void ConfigureDesignTimeServices(IServiceCollection serviceCollection)
    {
      serviceCollection.Decorate<IDatabaseModelFactory, CustomSqlServerDatabaseModelFactory>();
    }
}

Now run dotnet ef dbcontext scaffold. That's all.

Tip: You can easily debug your custom decorators by inserting a Debugger.Launch(); statement in the desired Create method. After you run the command, when the inserted statement will be hit you will be asked what application to open if you want to debug. Select Visual Studio and you are done.

NuGet packages used if needed:

  <ItemGroup>
    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.0-rtm.20502.6">
      <PrivateAssets>all</PrivateAssets>
      <!--<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>-->
    </PackageReference>
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="5.0.0-rc.1.20451.13" />
    <PackageReference Include="Scrutor" Version="3.2.2" />
  </ItemGroup>
Exclude tables when using Entity Framework Core Reverse Engineering
Share this