简体   繁体   中英

ef core new dbcontext executes OnModelCreating only once

we have regularly changing Database Data(every two weeks to once a month). Usually the latest data has to be used, but in some special cases older data is necessary.

The current info which version has to be used atm is stored in another table.

The Database looks like this, versioned Schema-Names with the same tables beneath it.

YYYYMMDD+Revision

myshema_202001011
    table1
myshema_202002011 and so on
    table1
myshema_202003011 and so on
    table1

I have build a Aspnet core (2.2) service with two DbContext classes, one for the static schemas that gets the current version to use and one for the changing schemas that accesses those data.

The static DbContext works just fine.

The problem is, even when i use the changing contaxt with a using like,

using (var _context = new ChangingDbContext()){}

the constructors and OnConfiguring are executed each time but the OnModelCreating method is only executed once . This leads to NOT updating to the current schemas.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);
    modelBuilder.HasAnnotation("ProductVersion", "2.2.6-servicing-10079");

    modelBuilder.Entity<my_table>(entity =>
    {
        entity.HasKey(e => e.key_adr);
        entity.ToTable("mytable", $"myshema{mySchemaVersion}");
    }); 
}

Has anyone a clue how to get a "really" new context where OnModelCreating is executed every time? Or maybe another solution how to handle those changing Schemas?

To continue from my comment. The below db table design allows you or users add as many as new fields to an object as they want. And I think it gives most flexible structure.

Let's assume in a eCommerce system, we provide 3 fields (Name, Code, Price) for the product. But we also allow users want to add their custom fields to their products (eg Promotion1Price, Promotion2Price, Discount, ...)

PRODUCT (ProductId, Name, Code, Price)

CUSTOMEFIELD (FieldId, FieldName, FieldType)

PRODUCT_CUSTOMFIELD (ProductId, FieldId, FieldValue)

Let me know if this doesn't serve your purpose right.

Solved by this Answer https://stackoverflow.com/a/41985226/6692289

Quote from Example in case it gets deleted.

Derived DbContext that replaces it's ModelCacheKey (and factory) with a Custom one.

 class MyDbContext : DbContext { public MyDbContext(string schema) { Schema = schema; } public string Schema { get; } protected override void OnConfiguring(DbContextOptionsBuilder options) => options .UseSqlServer("...") .ReplaceService<IModelCacheKeyFactory, MyModelCacheKeyFactory>(); protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.HasDefaultSchema(Schema); // ... } }

The factory that creates the Context with a specific key.

 class MyModelCacheKeyFactory : IModelCacheKeyFactory { public object Create(DbContext context) => new MyModelCacheKey(context); }

The custom ModelCacheKey per context.

 class MyModelCacheKey : ModelCacheKey { string _schema; public MyModelCacheKey(DbContext context) : base(context) { _schema = (context as MyDbContext)?.Schema; } protected override bool Equals(ModelCacheKey other) => base.Equals(other) && (other as MyModelCacheKey)?._schema == _schema; public override int GetHashCode() { var hashCode = base.GetHashCode() * 397; if (_schema != null) { hashCode ^= _schema.GetHashCode(); } return hashCode; } }

And using the Context like.

using (var _myContext = new MyDbContext(_schemaNameToUse)
{
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM