David Létourneau David Létourneau - 2 months ago 29
C# Question

How reuse an existing DbContext as base class for a new project?

I have an existing DbContext class that I want to use as a base class for my other web projects. That DbContext contain a really complete table structure to registrer companies and peoples with related information’s.

When starting a new project, I do not want to create the same structure again and again! So I try to reuse the existing DbContext as a base class for my new project and just adding the new tables needed to make it working as wanted in the new application.

But, I cannot find a way to make it working! The DbContext base class is like below, it came from another project:

public class TemplateDbContext
{
private readonly Guid _instanceId;
bool _disposed;
public Guid InstanceId { get { return _instanceId; } }
public TemplateDbContext ()
: base("name=" + GetConnectionStringName)
{
}

public static TemplateDbContext Create()
{
return new TemplateDbContext ();
}
private void SetOneToMany(DbModelBuilder modelBuilder)
{

}

private void SetManyToMany(DbModelBuilder modelBuilder)
{

}

private void SetOneToOne(DbModelBuilder modelBuilder)
{

}

private void SetOneNavigation(DbModelBuilder modelBuilder)
{

}

private void SetKeys(DbModelBuilder modelBuilder)
{

}

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

modelBuilder.Entity<IdentityUserClaim>().ToTable("MembershipClaims");
modelBuilder.Entity<IdentityUserRole>().ToTable("MembershipRoles");
modelBuilder.Entity<IdentityUserLogin>().ToTable("MembershipLogins");
modelBuilder.Entity<IdentityRole>().ToTable("Roles");
modelBuilder.Entity<Membership>().ToTable("Memberships");

SetKeys(modelBuilder);
SetOneNavigation(modelBuilder);
SetOneToOne(modelBuilder);
SetOneToMany(modelBuilder);
SetManyToMany(modelBuilder);
}

public static string GetConnectionStringName
{
get
{
...
}
}

public DbSet<UserProfile> UserProfiles
{
get;
set;
}

// I have many more DbSet defined here...
public override int SaveChanges()
{
...
}

public override async Task<int> SaveChangesAsync()
{
...
}

public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken)
{
...
}

public void SyncObjectState<TEntity>(TEntity entity) where TEntity : class, IObjectState
{
...
}

private void SyncObjectsStatePreCommit()
{
...
}

public void SyncObjectsStatePostCommit()
{
...
}

protected override void Dispose(bool disposing)
{
...
}
}


Here is the ApplicationDbContext for my new project :

public class ApplicationDbContext : TemplateDbContext
{
public DbSet<Fruit> Fruits { get; set; }
// I have many more DbSet define here...

private void SetOneToMany(DbModelBuilder modelBuilder)
{
...
}

private void SetManyToMany(DbModelBuilder modelBuilder)
{
...
}

private void SetOneToOne(DbModelBuilder modelBuilder)
{
...
}

private void SetOneNavigation(DbModelBuilder modelBuilder)
{
...
}

private void SetKeys(DbModelBuilder modelBuilder)
{
...
}

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
SetKeys(modelBuilder);
SetOneNavigation(modelBuilder);
SetOneToOne(modelBuilder);
SetOneToMany(modelBuilder);
SetManyToMany(modelBuilder);
}
}


As you could guest, this is not working at all and I don’t know how I can achieve the result I want. I even don’t know if it is possible without duplicating all the code from TemplateDbContext class.
The best things that I accomplished for now, it to generate the TemplateDbContext only, by executed the Add-Migration with Package Manager Console within the new project. So the migration missed all the DbSet defined into the ApplicationDbContext class.

What kind of structure I need to do that?

Answer

You can specify the name of Context when you enable migration and using the other commands in same way, you can find more info about this here.

enable-migrations -ContextTypeName <DbContext-Name-with-Namespaces> -MigrationsDirectory:<Migrations-Directory-Name>
Add-Migration -configuration <DbContext-Migrations-Configuration-Class-with-Namespaces> <Migrations-Name>
Update-Database -configuration <DbContext-Migrations-Configuration-Class-with-Namespaces> -Verbose

Note: Don't forget to change Default Project to be the same as ApplicationDbContext in Package Manager Console.

Also i think you forgot to call base.OnModelCreating(modelBuilder) when you override the method in ApplicationDbContext.