Search code examples
c#entity-framework-coredbcontextpartialpartial-classes

How to extend DbContext with partial class and partial OnModelCreating method in EntityFramework Core


I'm using EF Core and DatabaseFirst approach. My dbContext is created automatically by Scaffold-DbContext command.

I need to add some new DbSets into a dbContext and add into OnModelCreating method some additional code but after each scaffolding that added code are erased and I have to add it each time again.

What I want to do is to create another partial dbContext class and mark protected override void OnModelCreating(ModelBuilder modelBuilder) method as partial

but get errors:

A partial method cannot have access modifiers or the virtual, abstract, override, new, sealed, or extern modifiers.

A partial method may not have multiple implementing declarations

Here is a pseudo code:

MyDbContext1.cs - generated by Scaffold-DbContext

public partial class MyDbContext : DbContext
{
    public MyDbContext()
    {
    }

    public MyDbContext(DbContextOptions<MyDbContext> options)
        : base(options)
    {
    }

    public virtual DbSet<Client> Clients { get; set; }

    protected override partial void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Client>(entity =>
        {
            // some code ...
        }
    }
}

MyDbContext2.cs - this code I added each time into dbContext after scaffolding:

public partial class MyDbContext
{
    public virtual DbSet<JustAnotherEntity> AnotherEntity { get; set; }

    protected override partial void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<JustAnotherEntity>(entity =>
        {
            entity.HasKey(e => new {e.Id, e.IdAction, e.IdState})
                .ForSqlServerIsClustered(false);
        });
    }
}

Solution

  • EFCore 3 - They FINALLY fixed this!

    You can now implement OnModelCreatingPartial in a partial class like this. Note the partial keyword on both the class and method:

    public partial class RRStoreContext : DbContext
    {
        partial void OnModelCreatingPartial(ModelBuilder builder)
        {
            builder.Entity<RepeatOrderSummaryView>().HasNoKey();
        }
    }
    

    If you look at the generated context file - right at the very end of OnModelCreating(...) you'll see...

     OnModelCreatingPartial(modelBuilder);
    

    Note: I use scaffolding, but I needed to manually add HasNoKey for a stored procedure (with a custom return type that wasn't otherwise scaffolded).