【发布时间】:2013-07-10 04:50:49
【问题描述】:
我正在尝试使用实体框架的代码优先概念创建一个新数据库。然而,在运行代码时,虽然代码运行良好,但并未创建数据库(使用DropCreateDatabaseIfModelChanges 设置)。当我尝试从数据库中获取某些内容时,我看到了以下异常。
我的项目是使用具有通用服务和存储库构造的单独DataAccess 层设置的。所以我所有的实体、存储库和数据库上下文都在解决方案中的一个单独项目中。
我的global.asax 文件包含以下代码。
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<MyContext>());
如果新数据库不存在,这应该初始化一个新数据库,对吧?
我的数据库上下文类如下所示;
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>();
}
}
}
我根据互联网上的几篇教程和文章创建了这个课程。这对我来说都是新的,但据我所知,到目前为止一切似乎都是正确的。所以现在我正在使用的两个实体。它们被称为“项目”和“投资组合”。它们看起来像这样;
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 中。我已经尝试删除数据库并让代码重新创建它,但不幸的是没有用。我在这里遗漏了一些明显的东西吗?或者它可能是一个简单的事情,比如访问服务器来创建数据库?
注意:当我运行Database-Update -Script命令生成SQL代码时,似乎创建了创建所有表的正确SQL语句。
更新 1: 好的,多亏了一些cmets,我走得更远了。我已经向我的实体添加了两个属性来强制进行一些更改,并且我还创建了一个这样的自定义初始化程序;
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);
}
}
我还从上下文的构造函数中删除了初始化程序,所以这意味着我已经删除了这行代码;
Database.SetInitializer<MyContext>(new DropCreateDatabaseIfModelChanges<MyContext>());
之后我将这三行添加到我的 Global.asax 文件中;
Database.SetInitializer(new ForceDeleteInitializer());
MyContext c = new MyContext();
c.Database.Initialize(true);
在调试时,我现在遇到了这个异常;
这给了我以下信息:
- InnerException 说:提供者没有返回 ProviderManifestToken
- InnerException 中的 InnerException 说:“对于此操作,需要连接到主数据库。连接不能 使宽度成为“主”数据库,因为原始连接是 打开并且引用已从连接中删除。 请提供非开放连接”
在这些操作之后,数据库无法访问,因此很可能已被删除..
对此可以做些什么?我很可能无法访问主数据库,因为我的托管服务提供商当然不会给我适当的访问权限。
【问题讨论】:
-
代码和配置看起来不错,您可能被托管情况卡住了。 EF 希望创建您的 Db,其中包含一个特殊的帮助表(1 或 2 个哈希)。也许您可以从本地 Db 编写脚本并将其移动到托管 Db?
-
运行您的代码的用户帐户是否具有删除和创建数据库的必要权限?
-
@Henk,我刚刚尝试运行生成的 SQL 脚本。它用一条记录为我创建了一个 __MigrationHistory 表。我还通过添加“this.Database.Initialize(true)”行来修改上下文的构造函数。这没有给我一个错误,但也没有创建任何表。然后我从 MigrationHistory 表中删除了记录,我又遇到了同样的错误。所以我现在尝试在本地数据库上运行它,看看会发生什么。
-
@jlew,运行我代码的机器是我以管理员身份运行 VS2012 的开发电脑。
-
但也没有创建任何表。 当你有了它时,向模型添加一个虚拟属性。触发 DropAndCreate,夜间工作。
标签: c# entity-framework asp.net-mvc-4 ef-code-first entity-framework-5