本文介绍了实体框架5代码首先不创建数据库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! 我试图使用Entity Framework的代码第一个概念创建一个新的数据库。但是,当运行代码时,不会创建数据库(使用 DropCreateDatabaseIfModelChanges 设置),尽管代码运行正常。当我尝试从数据库中获取某些东西时,我看到以下异常。 我的项目是使用单独的 DataAccess 通用服务和仓库建设。所以我所有的实体,存储库和数据库环境都在解决方案中的一个单独的项目中。 我的 global.asax 文件包含以下代码段。 Database.SetInitializer(new DropCreateDatabaseIfModelChanges< MyContext>()); 如果不存在,应该初始化一个新的数据库,对吗? 我的数据库上下文类看起来像这样; 命名空间Website.DAL.Model { public class MyContext:DbContext { public IDbSet< Project>项目{get;组; } public IDbSet<投资组合>投资组合{get;组; } ///< summary> ///构造函数,我们提供要用于它的基类的connectionstring。 ///< / summary> public MyContext():base(MyConnectionString) {} static MyContext() {尝试 { Database.SetInitializer< MyContext>(new DropCreateDatabaseIfModelChanges< MyContext>()); } catch(异常) { throw; } } ///< summary> ///这个方法可以防止表名称的泛化 ///< / summary> ///< param name =modelBuilder>< / param> protected override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Conventions.Remove< System.Data.Entity.ModelConfiguration.Conventions.PluralizingTableNameConvention>(); } } } 我创建了这个类以下几个教程和互联网上的文章。这对我来说都是新鲜事物,但是据我所知,一切似乎都是正确的。所以现在我正在使用的两个实体。他们被称为项目和投资组合。他们看起来像这样; public class Portfolio { [Key] public Guid Id {get;组; } public String Name {get;组; } public DateTime StartDate {get;组; } public DateTime? EndDate {get;组; } public bool IsPublished {get;组; } public virtual ICollection< Project>项目{get;组; } } 和 public class Project { [Key] public Guid Id {get;组; } public DateTime StartDate {get;组; } public DateTime? EndDate {get;组; } public bool IsPublished {get;组; } public String标题{get;组; } 我正在使用的数据库是在外部服务器上运行的,与我正在使用的托管服务提供商我有一个SQL Server数据库启动并运行,并且数据库的连接字符串在网站项目的 web.config 中。我已经尝试删除数据库,让代码重新创建它,这不幸没有起作用。我在这里遗漏了什么吗?或者可以这样做是一个简单的事情,作为服务器创建数据库的权限? 注意:当我运行数据库更新 - 脚本命令生成SQL代码,似乎创建了正确的SQL语句来创建所有表。 更新1: strong> 好​​的,感谢一些评论,我进一步来了。我已经向我的实体添加了两个属性来强制进行一些更改,并且我也创建了一个这样的自定义初始值设置: public ForceDeleteInitializer类:IDatabaseInitializer< MyContext> { private readonly IDatabaseInitializer< MyContext> _initializer = new DropCreateDatabaseIfModelChanges< MyContext>(); public ForceDeleteInitializer() { // _ initializer = new ForceDeleteInitializer(); } public void InitializeDatabase(MyContext context) { //添加此命令以防止打开连接。参见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即时); _initializer.InitializeDatabase(context); } } 我还从建构函数我的上下文,所以这意味着我已经删除了这一行代码; Database.SetInitializer< MyContext>(new DropCreateDatabaseIfModelChanges< MyContext> ;()); 之后,我将这三行添加到我的Global.asax文件中; Database.SetInitializer(new ForceDeleteInitializer()); MyContext c = new MyContext(); c.Database.Initialize(true); 调试时我现在得到这个异常; InnerException说:提供者没有返回 ProviderManifestToken InnerException中的InnerException表示:对于此操作,需要连接到主数据库,连接不能为,因为原始数据库连接是打开,引用已从连接中删除请提供非开放连接 在这些动作之后,数据库是无法访问的,所以很可能被删除.. 可以做些什么呢?很可能我无法访问主数据库,因为我的主机提供者不会给我正确的访问权限。解决方案因为没有其他解决方案,我决定改变我的方法。 我已经首先创建了数据库,并确保正确的SQL用户被配置,我有访问权限。 然后我从Global.asax文件中删除了初始化程序和代码。之后,我在包管理器控制台中运行以下命令(因为分层设计我必须在控制台中选择正确的项目); 启用迁移 在启用迁移后,我对我的实体进行了最后一刻的更改我运行下面的命令来支持新的迁移; 添加迁移AddSortOrder $ / pre> 创建我的迁移后,我在控制台中运行以下命令,瞧,数据库已更新为我的实体; 更新数据库-Verbose 为了能够在运行迁移时种数据库,我已经覆盖了在启用迁移时创建的Configuraton.cs类中的Seed方法。这个方法的最终代码是这样的; protected override void Seed(MyContext context) { //迁移到最新版本后,将调用此方法。 //添加菜单项和页 if(!context.Menu.Any()&!context.Page.Any()) { context.Menu.AddOrUpdate(new Menu() { Id = Guid.NewGuid(), Name =MainMenu,描述=一些菜单, IsDeleted = false, IsPublished = true, PublishStart = DateTime.Now, LastModified = DateTime.Now, PublishEnd = null, MenuItems = new列表< MenuItem>() { new MenuItem() { Id = Guid.NewGuid(), IsDeleted = false, IsPublished = true, PublishStart = DateTime。现在, 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 }); } 尝试 { //你的代码... //如果你知道异常,也可以在尝试之前发生在SaveChanges context.SaveChanges(); } catch(DbEntityValidationException e) { // foreach(在e.EntityValidationErrors中为var eve) // { // Console.WriteLine (Entity of type \{0} \in state \{1} \具有以下验证错误:, // eve.Entry.Entity.GetType()。名称,eve.Entry.State); // foreach(var ve in eve.ValidationErrors) // { // Console.WriteLine( - 属性:\{0} \,错误:\ {1} \, // ve.PropertyName,ve.ErrorMessage); //} //} // throw; var outputLines = new List< string>(); foreach(eEEEityValidationErrors中的var eve) { outputLines.Add(string.Format({0}:类型为\{1} \ 在状态\{2} \中有以下验证错误:, DateTime.Now,eve.Entry.Entity.GetType()。Name,eve.Entry.State)); foreach(var e in eve.ValidationErrors) { outputLines.Add(string.Format( - 属性:\{0} \,错误: \{1} \, ve.PropertyName,ve.ErrorMessage)); } } System.IO.File.AppendAllLines(@c:\temp\errors.txt,outputLines); throw; } } 目前的缺点是我必须手动在包管理器控制台中使用(仅)2个命令进行迁移。但同时,这并不是动态发生的事实也是很好的,因为这可以防止对我的数据库的可能的修改。更多的一切都只是完美的。 I'm trying to create a new database using the code first concept of Entity Framework. However when running the code the database isn't created (using the DropCreateDatabaseIfModelChanges setting), though the code is running fine. I'm seeing the following exception when I try to get something from the database.My project is setup using a separate DataAccess layer with an generic service and repository construction. So all my entities, repository and also database context are in a separate project within the solution.My global.asax file contains the following piece of code.Database.SetInitializer(new DropCreateDatabaseIfModelChanges<MyContext>());This should initialise a new database if it isn't there, right?My database context class looks like this;namespace Website.DAL.Model{ public class MyContext : DbContext { public IDbSet<Project> Projects { get; set; } public IDbSet<Portfolio> Portfolios { get; set; } /// <summary> /// The constructor, we provide the connectionstring to be used to it's base class. /// </summary> public MyContext() : base("MyConnectionString") { } static MyContext() { try { Database.SetInitializer<MyContext>(new DropCreateDatabaseIfModelChanges<MyContext>()); } catch (Exception) { throw; } } /// <summary> /// This method prevents the plurarization of table names /// </summary> /// <param name="modelBuilder"></param> protected override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Conventions.Remove<System.Data.Entity.ModelConfiguration.Conventions.PluralizingTableNameConvention>(); } }}I've created this class following several tutorials and articles on the internet. It's all new to me, but as far as I can see everything seems correct so far. So now the two entities I'm using. They're called 'Project' and 'Portfolio'. They look like this;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<Project> Projects { get; set; } }Andpublic 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; } }The database I'm using is running on an external server, it came with the hosting provider I'm using. I've got a SQL Server database up and running and the connection string to the database is in the web.config of the website project. I've already tried removing the database and let the code recreate it, which unfortunately didn't work. Am I missing something obvious here? Or could it be a simple thing as access-rights to the server to create databases?Note: When I run the Database-Update -Script command to generate SQL code, it seems that the correct SQL statements to create all tables are created.UPDATE 1:Okay, thanks to some comments I came a bit further. I've added two properties to my entities to force some changes and I've also created an custom initializer like this;public class ForceDeleteInitializer : IDatabaseInitializer<MyContext> { private readonly IDatabaseInitializer<MyContext> _initializer = new DropCreateDatabaseIfModelChanges<MyContext>(); 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); } }I've also removed the initializer from the constructor of my context, so this mean i've remove this line of code;Database.SetInitializer<MyContext>(new DropCreateDatabaseIfModelChanges<MyContext>());After that i've added these three lines to my Global.asax file;Database.SetInitializer(new ForceDeleteInitializer());MyContext c = new MyContext();c.Database.Initialize(true);When debugging i'm now getting this exception;This gives me the following information:InnerException says: The provider didn't return aProviderManifestTokenInnerException in the InnerException says: "For this operation an connection to the masterdatabase is required. A connection can't bemade width the 'master'-database because the original connection isopened and the references has been removed from the connection.Please provide a non-open connection"After these action the database is inaccessible, so most likely deleted..What can possibly be done about this? It's most likely that I can't access the master database because my hostingprovider won't give me the proper access right ofcourse. 解决方案 Since no other solution came by I decided to change my approach.I've first created the database myself and made sure the correct SQL user was configured and I had access.Then I removed the initializer and the code from the Global.asax file. After that I ran the following command in the Package Manager Console (since the layered design I had to select the correct project in the console);Enable-MigrationsAfter the migrations where enabled and I made some last minute changes to my entities I ran the command below to scaffold an new migration;Add-Migration AddSortOrderAfter my migrations were created I ran the following command in the console and voila, the database was updated with my entities;Update-Database -VerboseTo be able to seed the database when running the migration i've overridden the Seed method in my Configuraton.cs class, which was created when enabling the migrations. The final code in this method is like this;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<MenuItem>() { 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<string>(); 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; } }The disadvantage at the moment is that I have to manually migrate with (only) 2 commands in the package manager console. But the same time, the fact that this doesn't happen dynamically is also good because this prevents possibly inwanted changes to my database. Further everything works just perfect. 这篇关于实体框架5代码首先不创建数据库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
08-29 20:02