2012-10-10 87 views
7

我試圖創建一個包含所有,將永遠在多個項目中重複使用的公共實體,如頁面,用戶,角色,導航等EF代碼第一:繼承的DbContext創建兩個數據庫

基地的DbContext這樣做我有一個ContextBase類繼承了DbContext並定義了我想要的所有DbSets。然後我有一個繼承ContextBase的Context類,我定義了特定於項目的DbSets。的類的定義如下:

public class ContextBase : DbContext 
{ 
    public virtual DbSet<User> 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<Building> 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<Context, Configuration>()); 

其中配置referes一類繼承DbMigrationsConfiguration並覆蓋種子的方法。

兩個上下文類在同一個命名空間中定義,但橫向組件(以便我可以更新多個現有項目的基礎項目不接觸該項目的具體代碼) - 不知道這是相關的。

我的問題: 運行此代碼時,它工作正常,但在數據庫中查看時,它實際上創建兩個不同的數據庫!一個包含所有基本實體表,一個包含所有基本表和自定義表。 CRUD操作僅在定製版本上執行(這顯然是我想要的),但爲什麼它會創建另一個的架構?

任何幫助表示讚賞,謝謝!

UPDATE:

下面的代碼是什麼我結束了。這不是理想的,但它的工作原理。我仍然希望得到有關如何改善這一問題的反饋意見,但同時我希望這有助於推動這一進程。我真的不推薦這樣做!這非常容易出錯,調試非常令人沮喪。我只是發佈這個看看是否有更好的想法或實現來實現這一點。

一(但不是唯一的)問題仍然存在就是MVC觀點,必須手動添加到項目中。我已經將它添加到Nuget包中,但是當VS連接到TFS時,需要2到3個小時才能將Nuget包應用於這麼多文件。藉助一些更多的工作和自定義View引擎,可以對視圖進行預編譯(http://blog.davidebbo.com/2011/06/precompile-your-mvc-views-using.html)。

該溶液被分成基本框架項目和自定義項目(每個類別包括其自己的模型和信息庫模式)。該框架項目的NuGet包打包,然後安裝在允許像用戶,角色和權限管理,內容管理等任何項目的通用功能的任何自定義項目(通常被稱爲鍋爐板),可以很容易地加入到任何新項目。這使得可以在任何現有的定製項目中遷移樣板的任何改進。

自定義數據庫初始化程序:

public class MyMigrateDatabaseToLatestVersion : IDatabaseInitializer<Context> 
{ 
    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); 
      } 
     } 
    } 
} 

框架的DB遷移配置:

public class FrameworkConfiguration: DbMigrationsConfiguration<Repository.ContextBase> 
{ 
    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); 
    } 
} 

自定義項目的DB遷移配置:

public class Configuration : DbMigrationsConfiguration<Repository.Context> 
{ 
    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, i.e. 
    public DbSet<Chart> Charts { get; set; } 

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

     //Assign the model configs, i.e. 
     modelBuilder.Configurations.Add(new ChartConfiguration()); 
    } 
} 

框架的DbContext:

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

在Global.asax AppStart的:

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

在web.config:

<connectionStrings> 
    <!--put the exact same connection string twice here and name it the same as the base and overridden context. That way they point to the same database. --> 
    <add name="Context" connectionString="Data Source=.\SQLEXPRESS; Initial Catalog=CMS2013; Integrated Security=SSPI;MultipleActiveResultSets=true;" providerName="System.Data.SqlClient"/> 
    <add name="ContextBase" connectionString="Data Source=.\SQLEXPRESS; Initial Catalog=CMS2013; Integrated Security=SSPI;MultipleActiveResultSets=true;" providerName="System.Data.SqlClient"/> 
</connectionStrings> 
+0

嘗試在基類中設置連接字符串(或從父類傳遞它)即公共ContextBase():base(「MyConnection」) –

+1

您是否也從ContextBase調用基礎?如果添加更多配置,它會爲每個配置創建一個數據庫嗎?嘗試添加配置,然後調用base.OnModelCreating。 – MrFox

+1

你曾經直接創建過一個'ContextBase'上下文嗎? ('new ContextBase()')如果你這樣做了,而你不想,你可以使用'ContextBase'' abstract'來確保編譯器標記嘗試這麼做。 – hvd

回答

5

(從評論)

你直接創建ContextBase對象,在一個通用的方法與ContextBase顯然是new T()作爲一種通用型的說法,所以對於任何ContextBase也initialisers運行。爲防止創建對象(如果不應直接實例化,如果始終使用派生的上下文),可以將該類標記爲abstract

3

ContextBase似乎有一個初始化以及..您可以通過刪除此

Database.SetInitializer<ContextBase>(null); 
+0

謝謝,我已經根據上面的@ hvd的評論找到了解決方案,但這個答案對我也有幫助。 +1 – hofnarwillie