我怎样才能让我的数据库使用entity frameworkCodeFirst种子?
数据库已成功创build(与表一样),但不会播种。 我花了好几个小时,读了大量的文章,但一直没有得到它。 有什么build议么?
在附注中,是否可以调用初始化程序,而不必在客户端中引用我的DatabaseContext?
我已经包含了所有我能想到的相关代码。 如果有其他事情会有所帮助,请让我知道。
我试过的东西:
- 我删除了我的连接string(因为它默认为sqlexpress,只是名称改变了)
- 我将DropCreateDatabaseIfModelChanges更改为DropCreateDatabaseAlways,仍然相同。
编辑:真奇怪的事情是一次,但我不知道如何或为什么它再次打破。 我假设连接string,但谁知道。
DatabaseInitializer.cs
public class DatabaseInitializer : DropCreateDatabaseIfModelChanges<DatabaseContext> { protected override void Seed(DatabaseContext context) { // Seeding data here context.SaveChanges(); } }
DatabaseContext.cs
public class DatabaseContext : DbContext { protected override void OnModelCreating(DbModelBuilder mb) { // Random mapping code } public DbSet<Entity1> Entities1 { get; set; } public DbSet<Entity2> Entities2 { get; set; } }
Global.asax.cs – Application_Start()
protected void Application_Start() { Database.SetInitializer<DatabaseContext>(new DatabaseInitializer()); AreaRegistration.RegisterAllAreas(); RegisterGlobalFilters(GlobalFilters.Filters); RegisterRoutes(RouteTable.Routes); }
客户端web.config
<connectionStrings> <add name="DatabaseContext" connectionString="data source=.\SQLEXPRESS;Database=Database;Integrated Security=SSPI;" providerName="System.Data.SqlClient" /> </connectionStrings>
解
为了文档的缘故,我在这里分享我的解决scheme。 浏览所有的评论将是一个痛苦无论如何。 最后,我有DatabaseInitializer和DatabaseContext在单独的类。 我不明白这些微小的变化是如何修正它的,但在这里。
DatabaseInitializer.cs
public class DatabaseInitializer : CreateDatabaseIfNotExists<DatabaseContext> { protected override void Seed(DatabaseContext context) { // Seed code here } }
DatabaseContext.cs
public class DatabaseContext : DbContext { public DatabaseContext() : base("MyDatabase") { } protected override void OnModelCreating(DbModelBuilder mb) { // Code here } public DbSet<Entity> Entities { get; set; } // Other DbSets }
Global.asax.cs – Application_Start()
protected void Application_Start() { Database.SetInitializer(new DatabaseInitializer()); AreaRegistration.RegisterAllAreas(); RegisterGlobalFilters(GlobalFilters.Filters); RegisterRoutes(RouteTable.Routes); }
这是我的DbContext类所有的样子,他们种子就好了:
public class MyDbContext : DbContext { public DbSet<MyClass> MyClasses { get; set; } protected override void OnModelCreating (DbModelBuilder modelBuilder) { base.OnModelCreating (modelBuilder); modelBuilder.Conventions.Remove<System.Data.Entity.ModelConfiguration.Conventions.PluralizingTableNameConvention> (); // Add any configuration or mapping stuff here } public void Seed (MyDbContext Context) { #if DEBUG // Create my debug (testing) objects here var TestMyClass = new MyClass () { ... }; Context.MyClasses.Add (TestMyClass); #endif // Normal seeding goes here Context.SaveChanges (); } public class DropCreateIfChangeInitializer : DropCreateDatabaseIfModelChanges<MyDbContext> { protected override void Seed (MyDbContext context) { context.Seed (context); base.Seed (context); } } public class CreateInitializer : CreateDatabaseIfNotExists<MyDbContext> { protected override void Seed (MyDbContext context) { context.Seed (context); base.Seed (context); } } static MyDbContext () { #if DEBUG Database.SetInitializer<MyDbContext> (new DropCreateIfChangeInitializer ()); #else Database.SetInitializer<MyDbContext> (new CreateInitializer ()); #endif } }
我已经使用了这种模式几次,它已经很好的为我。
即使正确调用Application_Start
Database.SetInitializer
,我的Seed
方法也没有被调用…原因很简单:如果你还没有任何实际使用数据库上下文的代码,初始化可能根本不被调用。
这是我悲伤的小故事。
首先,经验教训:
- 在使用上下文之前不会调用种子方法。
- 在连接debugging器之前,Global.asax.cs不会在第一次运行bc时运行断点。 要在Global.asax.cs上打一个断点,你可以在Web.config中添加一些空格,然后点击一个页面; 那么它会受到打击。
- 如果有VS连接到数据库,播种不会发生。 该应用程序将抛出一个错误。
所以,为了避免悲伤:
- 断开你的VS连接。
- 一次切换基类DropCreateDatabaseAlways。
- 打一个使用上下文的页面。
现在,悲伤:
- 我在我的Global.asax.cs文件中有我的自定义初始化类。 我在我的初始化种子方法有一个断点; 我开始申请,方法从未受到打击。 🙁
- 我在Application_Start的Database.SetInitializer调用中指向一个断点。 这从来没有受到打击。 🙁
- 我意识到我没有数据库模式更改,所以然后我将DropCreateDatabaseIfModelChanges更改为DropCreateDatabaseAlways。 依然没有。 🙁
- 我终于去了一个使用上下文的页面,它工作。 :/
您可以调用update-database
手动运行Configuration
类中的种子方法。 这也需要enable-migrations
。
PM> update-database Specify the '-Verbose' flag to view the SQL statements being applied to the target database. No pending code-based migrations. Running Seed method.
internal sealed class Configuration : DbMigrationsConfiguration<ProjectManager.Data.Database.ProjectDb> { public Configuration() { AutomaticMigrationsEnabled = false; } protected override void Seed(ProjectManager.Data.Database.ProjectDb context) { context.Status.AddOrUpdate( new Status() { Id = 1, Text = "New" }, new Status() { Id = 2, Text = "Working" }, new Status() { Id = 3, Text = "Completed" }, new Status() { Id = 4, Text = "Skipped" } ); } }
Global.asax文件中的以下更改适用于我:
旧代码:
protected void Application_Start() { Database.SetInitializer<mycontextclassname>(new DropCreateDatabaseAlways<mycontextclassname>()); ... }
新代码:
protected void Application_Start() { Database.SetInitializer<mycontextclassname>(new DropCreateDatabaseAlways<mycontextclassname>()); Database.SetInitializer(new Initializer()); ... }
我也很难得到Seed()被调用。 我很欣赏上面的所有有用的build议,使用DropCreateDatabaseAlways有一些运气…但并不总是!
最近,我在我的Repository的构造函数中添加了下面这行代码,效果很好:
public CatalogRepository() { _formCatalog.FormDescriptors.GetType(); }
触发Seed()被调用就足够了。 如果你已经尝试了所有的答案,但仍然没有运气,试试看。 祝你好运,这是一个非常耗时的经验。
您的示例中的种子事件将只触发一次,因为您使用DropCreateDatabaseIfModelChanges可以将其更改为DropCreateDatabaseAlways我认为,它应该每次触发种子事件。
编辑
这是我的DataContext
public WebContext() { DbDatabase.SetInitializer(new DropCreateDatabaseIfModelChanges<WebContext>()); }
在我发现Code First Features的时候,这件事发生在我身上。 这种情况经常发生在您首次使用Code First生成数据库时没有任何初始化策略。
如果您稍后决定实施基于DropCreateDatabaseIfModelChanges
的策略,但不修改您的模型,那么您的Seed
方法将不会被调用,因为数据库生成和策略只会在下次更改模型时应用。
如果这发生在你身上,试着修改你的模型来testing这个假设,我敢打赌,你的数据库将被填充;)
我还没有解决scheme,除了使用一个总是生成数据库的策略,但我真的不能把这个初始化策略放在你的DbContext中,因为这个类是在你生产环境中使用的,尽pipe初始化策略似乎主要用于stream畅的开发环境。
我刚刚遇到这个问题。 我已经从Web.config文件中删除了“connectionstrings”部分,并且当前应用程序开始运行 – 没有connectionstrings部分! 我加回部分,数据库不再播种。 这不是一个合适的解决scheme,但我只是在这里添加一个数据点,以便能够解决问题。
幸运的是,这只是一个小的“一次性”应用程序,我很快就会放弃…
精心确保您不会多次声明您的上下文variables。 如果播种后再次声明,种子将被覆盖。
我遇到了同样的问题,在改变了Global.asax
文件和Intializer
文件之后, 希望对那些仍然有数据播种问题的人有效。
Global.asax中的新代码:
protected void Application_Start() { Database.SetInitializer<mycontextclassname>(new DropCreateDatabaseAlways<mycontextclassname>()); Database.SetInitializer(new Initializer()); ... }
代码为Intializer文件:
public class Initializer : System.Data.Entity.DropCreateDatabaseAlways<Context>
更新后注意这个答案是不正确的! 我的数据库没有得到种子的原因仍然是一个谜(但它不是缺乏默认的基础构造函数调用,由@JaredReisinger指出)
我很欣赏这个问题有点老,但是我最终还是会有其他人。 这是我的价值:
我的数据库创build正常,但没有种子,即使我删除了数据库,并使用DropDatabaseInitialiser重新启动。
在阅读上面的代码后,我注意到我的上下文构造是这样的
public MyApp_Context() { // some code }
而上面的例子如下我的设置
public MyApp_Context() : base("name=MyApp_Context") { // some code }
是的,我没有调用基础对象的构造函数! 在这种情况下,除了播种工作外,我不会期望任何事情,但似乎是(可重复的)情况。
注意,我实际上并不需要在基础构造函数调用中提供上下文名称; 我只是这样写的,因为我是在复制上面的解决scheme的格式。 所以我的代码现在是这样的,种子在初始数据库创build工作。
public MyApp_Context() : base() { // some code }