问题描述
我试图创建一个使用实体框架的code第一个概念一个新的数据库。但是在运行$ C $当C数据库没有建立(使用 DropCreateDatabaseIfModelChanges
设置),虽然code运行良好。我看到以下情况例外,当我试图从数据库中获取的东西。
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.
我的的Global.asax
文件包含下面的一段code的。
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; }
}
和
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
。我已经尝试删除数据库,并让code重建它,不幸的是没有工作。我缺少明显的东西吗?或可能是因为访问权限服务器创建数据库一件简单的事?
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?
请注意:当我运行数据库更新-Script
命令生成SQL code,似乎是正确的SQL语句来创建创建的所有表。
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.
更新1:
好了,感谢一些意见我来到远一点。我已经添加了两个属性,我的实体迫使一些变化,我也创建了一个像这样的定制初始化;
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);
}
}
我也移除了上下文的构造函数初始化,所以这意味着我已经删除此行code的;
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>());
之后,我已经添加了这些三行到我的Global.asax文件;
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;
的这给了我下面的信息:的
- 的InnerException说:提供程序未返回
ProviderManifestToken - 的InnerException在InnerException说:对于这个操作需要对masterdatabase一个连接的连接是不可能的。
制作宽度master'数据库,因为原来的连接
打开和引用已经从连接移除。
请提供非开放连接
这些操作后无法访问数据库,因此最有可能被删除。
After these action the database is inaccessible, so most likely deleted..
什么都不可能对这样做吗?这是最有可能的,我无法访问主数据库,因为我的hostingprovider不会给我适当的访问权限ofcourse。
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.
我第一次创建自己的数据库,并确保正确的SQL用户进行配置,我不得不访问。
I've first created the database myself and made sure the correct SQL user was configured and I had access.
然后我删除了初始化,并从Global.asax文件中code。从那以后,我跑在包管理器控制台下面的命令(因为分层设计,我不得不选择在控制台中正确的项目);
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-Migrations
在这里启用,我做了一些最后一分钟改变我的实体,我跑下面的命令来脚手架一个新的迁移的迁移后;
After 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 AddSortOrder
在我的迁移创建我跑在控制台,瞧下面的命令,数据库是用我的实体更新;
After my migrations were created I ran the following command in the console and voila, the database was updated with my entities;
Update-Database -Verbose
要能够运行迁移我已经覆盖了种子法在我Configuraton.cs类,它是使迁移时创建的时候种子数据库。这种方法的最终code是这样的;
To 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;
}
}
目前最大的缺点是,我必须手动(只)在包管理器控制台两个命令迁移。但同时,事实证明这不会动态地发生也是好事,因为这prevents可能inwanted更改我的数据库。而且一切工作只是完美。
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 code-先不要创建数据库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!