Reputation: 2924
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);
});
}
}
Upvotes: 48
Views: 43328
Reputation: 1108
This is the complete solution :
You have a base DbContext Like this :
public partial class OrderContext : DbContext
{
public OrderContext(DbContextOptions<OrderContext> options) : base(options)
{
}
public virtual DbSet<Order> Orders { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//some code
OnModelCreatingPartial(modelBuilder);
}
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
}
Then you have a second partial class like this :
public partial class OrderContext : DbContext
{
partial void OnModelCreatingPartial(ModelBuilder modelBuilder)
{
// some other code
}
}
Upvotes: 0
Reputation: 146170
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).
Upvotes: 94
Reputation: 459
An alternative would be creating another context class that inherit from MyDbContext that actually include all the custom code. and then use this new class as your context. This way, there is no need to update the generated code.
public class MyDbContext2 : MyDbContext
{
public MyDbContext2()
{
}
public MyDbContext2(DbContextOptions<MyDbContext> options)
: base(options)
{
}
public virtual DbSet<JustAnotherEntity> AnotherEntity { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<JustAnotherEntity>(entity =>
{
entity.HasKey(e => new {e.Id, e.IdAction, e.IdState})
.ForSqlServerIsClustered(false);
});
}
}
Upvotes: 45
Reputation: 89361
You can't override methods in a partial class because all of the "parts" become a single class. But you can accomplish this by having the main OnModelCreating call a partial method. Like this:
public partial class Db : DbContext
{
partial void OnModelCreating2(ModelBuilder modelBuilder)
{
//additional config
}
}
public partial class Db : DbContext
{
public DbSet<Person> Persons { get; set; }
partial void OnModelCreating2(ModelBuilder modelBuilder);
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
OnModelCreating2(modelBuilder);
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Server=localhost;database=efcore2test;integrated security=true");
base.OnConfiguring(optionsBuilder);
}
}
Upvotes: 8