2

I want to fire OnModelCreating every new DataContext(new Entity()) ... But when i create a connection of a table , it works. When create a connection for another table, OnModelCreating doesnt work again, so because i got error,

the entity type <tableName> is not part of the model for the current context.

public class DataContext : DbContext
{
    private BaseEntity _entity;

    public DataContext(BaseEntity entity)
    {
        Database.Connection.ConnectionString = Parameters.ConnectionString;

        _entity = entity;
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        _entity.Map(modelBuilder); // this is dynamic fluent api here
    }
}
canmustu
  • 2,304
  • 4
  • 21
  • 34
  • You seem to think that a context can only serve one entity at a time. That's not true, not at all. It's highly uncommon what you do here. – Gert Arnold Jun 20 '18 at 20:11

2 Answers2

7

ta.speot.is is right that OnModelCreating fires only once because modelBuilder is cached. There are several cases when OnModelCreating is required to execute again. For example when multi-tenancy is implemented across sessions then one may require to fire OnModelCreating again.

When modelBuilder is created first time, then EF caches it to increase performance. it is cached using IDbModelCacheKeyProvider.CacheKey. OnModelCreating fires when it does not find Cache associated with CacheKey. So to get OnModelCreating fired again IDbModelCacheKeyProvider.CacheKey must be changed.

To change cache key, DbContext class must implement IDbModelCacheKeyProvider. When new cache key is returned In CacheKey property of IDbModelCacheKeyProvider then OnModelCreating event fires again.

For example see following code block:

public class TenantContext : DbContext, IDbModelCacheKeyProvider
{
    string IDbModelCacheKeyProvider.CacheKey {
        get { return tenentID.ToString(); }
    }
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
    }
}

When tenantID is changed, it forces OnModelCreating to execute because cache might not be available for new tenantID.

Note: CacheKey should be changed only if it is very urgent. Frequent change in CacheKey will decrease performance.

0

The manual has got you covered!

DbContext.OnModelCreating Method (DbModelBuilder)

...

Remarks

Typically, this method is called only once when the first instance of a derived context is created. The model for that context is then cached and is for all further instances of the context in the app domain. This caching can be disabled by setting the ModelCaching property on the given ModelBuidler [sic], but note that this can seriously degrade performance. More control over caching is provided through use of the DbModelBuilder and DbContextFactory classes directly.

Although if it's possible you might want to explore a generic DbContext like public class DataContext<TBaseEntity> : DbContext. This will lead you to an architecture where you have one DataContext type per TBaseEntity type.

Community
  • 1
  • 1
ta.speot.is
  • 26,914
  • 8
  • 68
  • 96
  • I can't use generic, not usable for my project. Unit Of Work blocks it in my project. This usage is more useful for me for now. – canmustu Sep 04 '17 at 10:44
  • I'm already creating DataContext for every entity when there is an operation for db. But after first creating of datacontext, onmodelconfiguring doesnt work anymore. But i have to change fluent api so i have to fire onmodelcreating. – canmustu Sep 04 '17 at 10:45
  • Is there a way to run a fluent api for DbModelBuilder at runtime ? – canmustu Sep 04 '17 at 10:46
  • *But after first creating of datacontext, onmodelconfiguring doesnt work anymore* Yes so ... *this method is called only once ... model for that context is then cached ... caching can be disabled by setting the ModelCaching property on the given ModelBuidler [sic]* – ta.speot.is Sep 04 '17 at 10:46
  • And if that doesn't work ... *More control over caching is provided through use of the DbModelBuilder and DbContextFactory classes directly.* – ta.speot.is Sep 04 '17 at 10:48
  • I'm on it that disable caching – canmustu Sep 04 '17 at 10:49
  • Is there easy way to disable caching or do I have to create custom DbModelBuilder ? – canmustu Sep 04 '17 at 10:55
  • This might be what you need https://stackoverflow.com/q/29708128/242520 – ta.speot.is Sep 04 '17 at 11:09
  • Okay, this is creating new DbModelBuilder. I guess, disabling cache code is not exist easly. – canmustu Sep 04 '17 at 11:10