我試圖創建一個包含所有,將永遠在多個項目中重複使用的公共實體,如頁面,用戶,角色,導航等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>
嘗試在基類中設置連接字符串(或從父類傳遞它)即公共ContextBase():base(「MyConnection」) –
您是否也從ContextBase調用基礎?如果添加更多配置,它會爲每個配置創建一個數據庫嗎?嘗試添加配置,然後調用base.OnModelCreating。 – MrFox
你曾經直接創建過一個'ContextBase'上下文嗎? ('new ContextBase()')如果你這樣做了,而你不想,你可以使用'ContextBase'' abstract'來確保編譯器標記嘗試這麼做。 – hvd