EF代码优先:inheritance的dbcontext创建两个数据库

我正在尝试创建一个基本dbcontext,其中包含所有常用实体,这些实体将始终在多个项目中重用,如页面,用户,角色,导航等。

这样做我有一个ContextBase类inheritanceDbContext并定义我想要的所有DbSet。 然后我有一个Context类inheritanceContextBase,我在其中定义项目特定的DbSet。 这些类定义如下:

public class ContextBase : DbContext { public virtual DbSet Users { get; set; } //more sets protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations.Add(new UsersConfiguration()); //add more configurations } } public class Context : ContextBase { public DbSet Buildings { get; set; } //some more project specific sets protected override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Configurations.Add(new BuildingsConfiguration()); //add more project specific configs } } 

在我的global.asax中:

 Database.SetInitializer(new MigrateDatabaseToLatestVersion()); 

其中Configuration引用inheritanceDbMigrationsConfiguration并重写Seed方法的类。

这两个上下文类在同一名称空间中定义,但是交叉程序集(为了我可以在多个现有项目中更新基础项目而不触及项目特定代码) – 不确定这是否相关。

我的问题:运行此代码时,它工作正常,但在查看数据库时,它实际上创建了两个不同的数据库! 一个包含所有基本实体表,另一个包含BOTH基表和自定义表。 CRUD操作只在自定义版本上执行(这显然是我想要的),但为什么它也创建了另一个版本的模式?

任何帮助表示赞赏,谢谢!

更新:

以下代码是我最终得到的。 它并不理想,但它有效。 我仍然希望获得有关如何改进这一点的反馈,但与此同时,我希望这有助于推动这一进程。 我真的不推荐这样做! 它非常容易出错并且非常令人沮丧。 我只是发布这个,看看是否有更好的想法或实现来实现这一目标。

仍然存在的一个(但不是唯一的)问题是必须手动将MVC视图添加到项目中。 我已经将它添加到Nuget包中,但是当VS连接到TFS时,需要2到3个小时来应用具有如此多文件的nuget包。 通过一些更多工作和自定义View引擎,可以预编译视图( http://blog.davidebbo.com/2011/06/precompile-your-mvc-views-using.html )。

该解决方案分为Base Framework项目和Custom项目(每个类别包括其自己的模型和存储库模式)。 框架项目打包在Nuget包中,然后安装在任何自定义项目中,允许任何项目的常用function,如用户,角色和权限管理,内容管理等(通常称为Boiler Plate),可以轻松添加到任何新项目。 这允许在任何现有的自定义项目中迁移样板的任何改进。

定制数据库初始化器:

 public class MyMigrateDatabaseToLatestVersion : IDatabaseInitializer { public void InitializeDatabase(Context context) { //create the base migrator var baseConfig = new FrameworkConfiguration(); var migratorBase = new DbMigrator(baseConfig); //create the custom migrator var customConfig = new Configuration(); var migratorCustom = new DbMigrator(customConfig); //now I need to check what migrations have not yet been applied //and then run them in the correct order if (migratorBase.GetPendingMigrations().Count() > 0) { try { migratorBase.Update(); } catch (System.Data.Entity.Migrations.Infrastructure.AutomaticMigrationsDisabledException) { //if an error occured, the seed would not have run, so we run it again. baseConfig.RunSeed(context); } } if (migratorCustom.GetPendingMigrations().Count() > 0) { try { migratorCustom.Update(); } catch (System.Data.Entity.Migrations.Infrastructure.AutomaticMigrationsDisabledException) { //if an error occured, the seed would not have run, so we run it again. customConfig.RunSeed(context); } } } } 

Framework的数据库迁移配置:

 public class FrameworkConfiguration: DbMigrationsConfiguration { public Configuration() { AutomaticMigrationsEnabled = false; } public void RunSeed(Repository.ContextBase context) { Seed(context); } protected override void Seed(Repository.ContextBase context) { // This method will be called at every app start so it should use the AddOrUpdate method rather than just Add. FrameworkDatabaseSeed.Seed(context); } } 

Custom Project的数据库迁移配置:

 public class Configuration : DbMigrationsConfiguration { public Configuration() { AutomaticMigrationsEnabled = false; } public void RunSeed(Repository.Context context) { Seed(context); } protected override void Seed(Repository.Context context) { // This method will be called at every app start so it should use the AddOrUpdate method rather than just Add. CustomDatabaseSeed.Seed(context); } } 

自定义DbContext

 //nothing special here, simply inherit ContextBase, IContext interface is purely for DI public class Context : ContextBase, IContext { //Add the custom DBsets, ie public DbSet Charts { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); //Assign the model configs, ie modelBuilder.Configurations.Add(new ChartConfiguration()); } } 

框架DbContext:

 //again nothing special public class ContextBase: DbContext { //example DbSet's public virtual DbSet Users { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder); } 

在global.asax AppStart中:

  //first remove the base context initialiser Database.SetInitializer(null); //set the inherited context initializer Database.SetInitializer(new MyMigrateDatabaseToLatestVersion()); 

在web.config中:

      

(来自评论)

您正在直接创建ContextBase对象,显然是在使用ContextBase作为generics类型参数的generics方法中的new T() ,因此ContextBase任何初始化程序也会运行。 要防止创建ContextBase对象(如果永远不应该直接实例化,如果应始终使用派生的上下文),则可以将该类标记为abstract

你的ContextBase似乎也有一个初始化器。你可以删除它

 Database.SetInitializer(null);