entity framework5代码优先不创建数据库

我正在尝试使用Entity Framework的代码优先概念创建一个新数据库。 但是,在运行代码时,不会创建数据库(使用DropCreateDatabaseIfModelChanges设置),尽管代码运行正常。 当我尝试从数据库中获取内容时,我看到以下exception。

在此处输入图像描述

我的项目使用单独的DataAccess层进行设置,该层具有通用服务和存储库构造。 因此,我的所有实体,存储库和数据库上下文都在解决方案中的单独项目中。

我的global.asax文件包含以下代码。

 Database.SetInitializer(new DropCreateDatabaseIfModelChanges()); 

这应该初始化一个新的数据库,如果它不存在,对吧?

我的数据库上下文类看起来像这样;

 namespace Website.DAL.Model { public class MyContext : DbContext { public IDbSet Projects { get; set; } public IDbSet Portfolios { get; set; } ///  /// The constructor, we provide the connectionstring to be used to it's base class. ///  public MyContext() : base("MyConnectionString") { } static MyContext() { try { Database.SetInitializer(new DropCreateDatabaseIfModelChanges()); } catch (Exception) { throw; } } ///  /// This method prevents the plurarization of table names ///  ///  protected override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Conventions.Remove(); } } } 

我在互联网上的几篇教程和文章后创建了这个课程。 这对我来说都是新的,但据我所知,到目前为止,一切似乎都是正确的。 所以现在我正在使用的两个实体。 他们被称为“项目”和“投资组合”。 它们看起来像这样;

 public class Portfolio { [Key] public Guid Id { get; set; } public String Name { get; set; } public DateTime StartDate { get; set; } public DateTime? EndDate { get; set; } public bool IsPublished { get; set; } public virtual ICollection Projects { get; set; } } 

 public class Project { [Key] public Guid Id { get; set; } public DateTime StartDate { get; set; } public DateTime? EndDate { get; set; } public bool IsPublished { get; set; } public String Title { get; set; } } 

我正在使用的数据库在外部服务器上运行,它与我正在使用的托管服务提供商一起提供。 我已启动并运行SQL Server数据库,并且数据库的连接字符串位于网站项目的web.config中。 我已经尝试删除数据库并让代码重新创建它,但遗憾的是它没有用。 我错过了一些明显的东西吗? 或者作为服务器的访问权限创建数据库可能是一件简单的事情吗?

注意:当我运行Database-Update -Script命令生成SQL代码时,似乎创建了用于创建所有表的正确SQL语句。

更新1:好的,感谢一些评论,我进一步了解。 我已经为我的实体添加了两个属性来强制进行一些更改,我还创建了一个这样的自定义初始化程序;

 public class ForceDeleteInitializer : IDatabaseInitializer { private readonly IDatabaseInitializer _initializer = new DropCreateDatabaseIfModelChanges(); public ForceDeleteInitializer() { //_initializer = new ForceDeleteInitializer(); } public void InitializeDatabase(MyContext context) { //This command is added to prevent open connections. See http://stackoverflow.com/questions/5288996/database-in-use-error-with-entity-framework-4-code-first context.Database.ExecuteSqlCommand("ALTER DATABASE borloOntwikkel SET SINGLE_USER WITH ROLLBACK IMMEDIATE"); _initializer.InitializeDatabase(context); } } 

我也从我的上下文的构造函数中删除了初始化程序,所以这意味着我删除了这行代码;

 Database.SetInitializer(new DropCreateDatabaseIfModelChanges()); 

之后我将这三行添加到我的Global.asax文件中;

 Database.SetInitializer(new ForceDeleteInitializer()); MyContext c = new MyContext(); c.Database.Initialize(true); 

调试时我现在得到这个例外; 在此处输入图像描述

这给了我以下信息:

  • InnerException说:提供者没有返回ProviderManifestToken
  • InnerException中的InnerException表示:“对于此操作,需要连接到masterdatabase。无法建立连接宽度’master’数据库,因为打开了原始连接并且已从连接中删除了引用。请提供非开放式连接“

执行这些操作后,数据库无法访问,因此很可能已删除..

有什么可以做的呢? 我很可能无法访问master数据库,因为我的hostingprovider不会给我正确的访问权限。

由于没有其他解决方案,我决定改变我的方法。

我自己首先创建了数据库并确保配置了正确的SQL用户并且我有权访问。

然后我从Global.asax文件中删除了初始化程序和代码。 之后我在Package Manager Console中运行了以下命令(因为分层设计我必须在控制台中选择正确的项目);

 Enable-Migrations 

在启用了迁移之后,我对我的实体做了最后一分钟的更改,我运行了下面的命令来支持新的迁移;

 Add-Migration AddSortOrder 

创建迁移后,我在控制台中运行以下命令,然后使用我的实体更新数据库;

 Update-Database -Verbose 

为了能够在运行迁移时为数据库设定种子,我在Configuraton.cs类中重写了Seed方法,该类是在启用迁移时创建的。 这个方法的最终代码是这样的;

 protected override void Seed(MyContext context) { // This method will be called after migrating to the latest version. //Add menu items and pages if (!context.Menu.Any() && !context.Page.Any()) { context.Menu.AddOrUpdate(new Menu() { Id = Guid.NewGuid(), Name = "MainMenu", Description = "Some menu", IsDeleted = false, IsPublished = true, PublishStart = DateTime.Now, LastModified = DateTime.Now, PublishEnd = null, MenuItems = new List() { new MenuItem() { Id = Guid.NewGuid(), IsDeleted = false, IsPublished = true, PublishStart = DateTime.Now, LastModified = DateTime.Now, PublishEnd = null, Name = "Some menuitem", Page = new Page() { Id = Guid.NewGuid(), ActionName = "Some Action", ControllerName = "SomeController", IsPublished = true, IsDeleted = false, PublishStart = DateTime.Now, LastModified = DateTime.Now, PublishEnd = null, Title = "Some Page" } }, new MenuItem() { Id = Guid.NewGuid(), IsDeleted = false, IsPublished = true, PublishStart = DateTime.Now, LastModified = DateTime.Now, PublishEnd = null, Name = "Some MenuItem", Page = new Page() { Id = Guid.NewGuid(), ActionName = "Some Action", ControllerName = "SomeController", IsPublished = true, IsDeleted = false, PublishStart = DateTime.Now, LastModified = DateTime.Now, PublishEnd = null, Title = "Some Page" } } } }); } if (!context.ComponentType.Any()) { context.ComponentType.AddOrUpdate(new ComponentType() { Id = Guid.NewGuid(), IsDeleted = false, IsPublished = true, LastModified = DateTime.Now, Name = "MyComponent", PublishEnd = null, PublishStart = DateTime.Now }); } try { // Your code... // Could also be before try if you know the exception occurs in SaveChanges context.SaveChanges(); } catch (DbEntityValidationException e) { //foreach (var eve in e.EntityValidationErrors) //{ // Console.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:", // eve.Entry.Entity.GetType().Name, eve.Entry.State); // foreach (var ve in eve.ValidationErrors) // { // Console.WriteLine("- Property: \"{0}\", Error: \"{1}\"", // ve.PropertyName, ve.ErrorMessage); // } //} //throw; var outputLines = new List(); foreach (var eve in e.EntityValidationErrors) { outputLines.Add(string.Format( "{0}: Entity of type \"{1}\" in state \"{2}\" has the following validation errors:", DateTime.Now, eve.Entry.Entity.GetType().Name, eve.Entry.State)); foreach (var ve in eve.ValidationErrors) { outputLines.Add(string.Format( "- Property: \"{0}\", Error: \"{1}\"", ve.PropertyName, ve.ErrorMessage)); } } System.IO.File.AppendAllLines(@"c:\temp\errors.txt", outputLines); throw; } } 

目前的缺点是我必须在包管理器控制台中使用(仅)2个命令手动迁移。 但同时,这不会动态发生的事实也很好,因为这可以防止对我的数据库进行有害的更改。 此外,一切都很完美。

+1详细问题。

检查您的连接字符串是否指向正确的数据库,并添加这样的授权属性以访问您的数据库:

  

初始化它运行以下代码来创建您的数据库:

context.Database.CreateIfNotExists();

首先从上下文类的构造函数参数中删除Db名称,并在连接字符串上提供Db_name,然后尝试重建解决方案并运行应用程序,它将为您的应用程序创建数据库。

例如 :

我没有在构造函数参数上传递Db-Name

 public EmployeeContext() : base() { Database.SetInitializer(new DropCreateDatabaseIfModelChanges()); } 

在连接字符串上,我传递的是Db-name,如下所示。