Efcore: Ability to exclude/skip/ignore parts of the model from migrations so that a table is not created (for overlapping bounded contexts)

Created on 28 Jul 2015  ·  43Comments  ·  Source: dotnet/efcore

I suggest having an attribute that can be applied to DbSet properties in a DbContext, which indicates whether or not to include them in the migration scaffolding process.

An example use case is when part of an application's database is replicated from another environment. Replicated entities will be included in the same DbContext as custom-developed entities so they can be queried. During development many migrations may be performed. Each time a migration is scaffolded, the replicated entities will be added to the migration, and then must be removed manually.

If an attribute only used for EF commands is too polluting to include in the DbContext, some alternatives might be: an additional config file that can be specified on the command line listing which entities should be excluded. Or perhaps additional command line arguments that allow a migration to be generated for specified entities only instead of scanning and comparing all entities.

Also consider the scenario of inherited models when looking at this feature https://github.com/aspnet/EntityFramework/issues/5572

area-migrations area-model-building closed-fixed punted-for-3.0 type-enhancement

Most helpful comment

I just found a workaround

  1. Create another DbContext that inherit your DbContext, for example MigrationDbContext. Override the OnModelCreating method and ingore entities that you want it's table not being generated.
 protected override void OnModelCreating(ModelBuilder builder)
 {
     base.OnModelCreating(builder);
     builder.Ignore<Category>();
 }
  1. Create another class that implement IDbContextFactory. For example
    public class MigrationContextFactory : IDbContextFactory<MigrationDbContext>
    {
        public MigrationDbContext Create()
        {
            var optionsBuilder = new DbContextOptionsBuilder<MigrationDbContext>();
            optionsBuilder.UseSqlite("Data Source=blog.db");

            return new MigrationDbContext(optionsBuilder.Options);
        }
    }

The migration tool will discover this MigrationContextFactory and use the MigrationDbContext.

All 43 comments

Agreed that this would be good to enable. Generalized the title a bit as an attribute may or may not be the best way to do this. An attribute may be good sugar over a more powerful hook to exclude parts of the model.

Moving to backlog as we will look at this after the first stable release.

+1, this to would be extremely useful.

+1

+1

+1 any status on this item?

+1 any status on this item?

No updates. We want to do it, but there are several items higher than it on the backlog.

Those items listed as higher on the backlog have now been closed. When can we expect inclusion to a sprint?

The main features we talk about being higher priority are the ones listed here https://docs.microsoft.com/en-us/ef/efcore-and-ef6/features. There is still quite a list of them that have not been implemented.

I just found a workaround

  1. Create another DbContext that inherit your DbContext, for example MigrationDbContext. Override the OnModelCreating method and ingore entities that you want it's table not being generated.
 protected override void OnModelCreating(ModelBuilder builder)
 {
     base.OnModelCreating(builder);
     builder.Ignore<Category>();
 }
  1. Create another class that implement IDbContextFactory. For example
    public class MigrationContextFactory : IDbContextFactory<MigrationDbContext>
    {
        public MigrationDbContext Create()
        {
            var optionsBuilder = new DbContextOptionsBuilder<MigrationDbContext>();
            optionsBuilder.UseSqlite("Data Source=blog.db");

            return new MigrationDbContext(optionsBuilder.Options);
        }
    }

The migration tool will discover this MigrationContextFactory and use the MigrationDbContext.

+1, This would make it possible to use ef core in plugin based architectures with each context inheriting from the core context with working relationships between contexts.

+1

+1

+100

+1

Hope quickly,thank you

To add to this, It would be nice to be able to add IgnoreBase or OnlyDeclared type options.

Though I think you would have to do something like
ModelB.Except(ModelA)

There would be some very interesting cases such as when HasValue<> is used on a base entity

Also If this goes into design, There should be a "depends on" migration attribute added to ensure that the tables that are required for the derived DBContext is in place

This could be implemented as either

  1. Must have migration A from dbcontext B
  2. Tables A, B must exists with columns A.A, A.B, B.A, B.B ect.

+1 bump

+100500

+1

+1

I am wondering does this means if I have IdentityDbContext & DbContext, and ApplicationUser (which is part of the IdentityDbContext & also part of the DbContext) will be created twice?

Right now I have 2 different contexts:

public class ApplicationDbContext: DbContext
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options): base(options)
        {
        }

        public DbSet<Course> Courses { get; set; }

        public DbSet<Enrollment> Enrollments { get; set; }

        public DbSet<Domain> Domains { get; set; }
    }
    public class ApplicationIdentityDbContext: IdentityDbContext<ApplicationUser>
    {
        public ApplicationIdentityDbContext(DbContextOptions<ApplicationIdentityDbContext> options): base(options)
        {
        }
    }

However, what I am trying to do is put those 2 contexts into 2 databases. However, when I use ApplicationIdentityDbContext for migration it will create all table in one database. If I use ApplicationDbContext it will only create Courses & Enrollments, Domains & ApplicationUser tables.

Any idea how I can solve this issue?

Since no one made it explicit apart from the title on the “overlapping bounded contexts”, I add that this would be nice to have when working with DDD (Domain-Driven Design) so that beginners on that subject like me can find this more easily next time when searching for the term DDD.

Any update about this?

@arnvanhoutte:

<br />
divega modified the milestones: Backlog, 3.0.0 27 days ago

It's planned for version 3.0.0

+1
It will be useful for work within mixed fixed tables and migration tables making migration genered table working together.

+1, definitely

Also very useful when database model is shared with another application, which handles migrations for some entities, but not all.

Note to implementer: Update the obsolete ToView method to call this in order to preserve its old semantics.

+1 this is key to DDD that implement a common context where there is a need for referential integrity from other contexts (multi-tenant or references to users or other common elements)

In EF6 we could hack this by implementing a CSharpMigrationCodeGenerator which overrode Generate commands to check the schema name and just return. Have attempted this with a MigrationsModelDiffer in EF Core, please see my next post which links to an example of what I have done to implement this

For anybody that is interested, I have implemented a workaround that I believe allows this to work when the elements you want to exclude are part of a different schema in the database (which is what I wanted to do).

I have included this as an example in an issue I have raised here: https://github.com/aspnet/EntityFrameworkCore/issues/15828

Let me know if this helps anyone

Consider also the case of excluding FKs from the database: #15854

Proposing punt...

I see that another reported issue was marked as a duplicate of this one...

https://github.com/aspnet/EntityFrameworkCore/issues/14283

I'm not seeing how this is a duplicate of that issue, and was wondering if any progress had been made or fix found for the issue of subsequent migrations attempting to re-create tables that have already been created in previous migrations. It's like instead of attempting an 'ALTER TABLE' process, the software punts and decides to just re-create the table. This is NOT a good thing.

If I recall correctly, last year things were not so messed up with EF Core and related technologies. Today, there seems to be a lot of packages incompatible with newer ones (to be expected to some degree), but I'm also finding newer packages and technologies are not working as they should. Case in point: MySql package for EF Core has no default mechanism to convert bit to boolean. This is very basic stuff.

Anyway, enough of my rant... is there a fix to prevent ef core migrations from attempting to re-create tables that already exist?

I'm really hoping this is just some configuration switch or migration setting I missed or something and not standard behavior for a product like ef core.

@echuck66 It sounds like your issue is different to the feature that is being tracked here. Can you please file a new issue and include a small, runnable project/solution or complete code listing that demonstrates the behavior you are seeing.

...disregard. I think I figured out what's going on... ef core is tracking updates to the schema in the project snapshot file. It was missing.

Also consider an attribute for at least some of this. (If it doesn't get done with the fluent API, then create a new issue for it.) See https://github.com/aspnet/EntityFrameworkCore/issues/18719#issuecomment-554751397

Proposing punt...

This was punted for 3.0 but didn't make it? What's the new ETA for this feature? It would be of great benifit for the corporation I'm working for.

@MBroertjes We're still working on planning, but it's looking like this will be in 5.0, hence the milestone currently assigned.

I hope this feature can be moved up, this is a really wanted feature.

I solved it checking from where the entity builder is called, (from "add-migration Xyz" command or the normal dbContext operations) If a migration operation calls the builder, I ignore the entity that I want to ignore just for migration purposes.
Here is my workaround;
https://stackoverflow.com/a/62281191/1928672

Was this page helpful?
0 / 5 - 0 ratings