实体框架代码首次部署到生产主机期间的迁移不起作用

时间:2014-01-30 18:43:51

标签: entity-framework visual-studio-2013 entity-framework-6

我正在使用VS2013和Entity Framework 6.1来对抗SQL 2012。

当我使用Code First在Dev中创建我的类和表时,它工作正常。 当我通过Web Deploy发布到我的第三方主机时,所有部署都会部署,但在数据库中没有创建任何表。连接字符串/ s包含具有对数据库的表创建访问权限的用户的相应用户名和密码。 (经过测试,因为我通过SSMS使用相同的登录名/密码 在托管SQL服务器上成功创建表) 数据库发布连接字符串正在正确生成并具有正确的值。

当我使用Execute Code First Migrations复选框部署ASP.Net MVC应用程序时,该应用程序会在托管服务器上引发500错误。

对可能出现的问题有什么看法?

3 个答案:

答案 0 :(得分:1)

听起来这是对VS Web部署功能如何处理EFCF迁移的误解。

通常(非EFCF),VS会将您的文件发布到远程服务器并更新数据库架构。部署完成后,所有更改都已应用。

通过EFCF迁移,情况并非如此。 VS的部署将修改您的web.config以设置数据库所需的连接字符串。这反映在已发布的文件中,但尚未触及数据库。在迁移代码运行之前,不会对DB进行更改。默认情况下,第一次代码初始化DbContext时会发生这种情况; DbInitializer将执行尚未应用的任何迁移。通常,这意味着您必须从您的站点请求页面才能触发此过程。

对我的评论进行一点阐述:

  

手动更改架构不是一个很好的解决方案,因为它会阻止迁移从以后运行(“表Foo已存在”类型错误)。

如果您对数据库进行了与迁移代码不兼容的更改,您将从EF获得异常。例如,您可能有此迁移:

public override void Up()
{
    CreateTable(
        "dbo.Foo",
        c => new
            {
                Id = c.Int(nullable: false, identity: true),
                Value = c.String(nullable: false, maxLength: 200),
            })
        .PrimaryKey(t => t.Id);

}

如果您手动创建了表Foo(例如,因为部署后没有看到它),则EF无法再应用此迁移,并抛出异常。这可能是您看到的HTTP 500错误的原因。

答案 1 :(得分:1)

出于某种原因,我必须确定已部署的Web.config中添加了EntityFramework部分,该部分不在我的本地版本的Web.config中。该错误是由EntityFramework部分引起的,但没有部分描述符指定存在EntityFramework部分。

我添加了部分描述符,一切正常。

我不确定为什么在部署内容时发生了转换,但转换不完整。

答案 2 :(得分:0)

我会在你的应用程序中设置错误页面。

Web.config下的<system.web>,你会有

<customErrors mode="On" defaultRedirect="~/Error/Index">
  <error statusCode="400" redirect="~/Error/Error400" />
  <error statusCode="403" redirect="~/Error/Error403" />
  <error statusCode="404" redirect="~/Error/Error404" />
</customErrors>

因此,defaultRedirect会捕获500错误。

您的Error控制器可能如下所示。

public class ErrorController : Controller
{
    public ActionResult Index()
    {
        return View("Error");
    }

    public ActionResult Error400()
    {
        return View("Error400");
    }

    public ActionResult Error403()
    {
        return View("Error403");
    }

    public ActionResult Error404()
    {
        return View("Error404");
    }
}

您的Error视图(我在Views\Shared目录中)看起来如下所示。

@{
    Layout = "~/Views/Shared/_Layout_Blank.cshtml";
    ViewBag.Title = "Application Error";
}

@model System.Web.Mvc.HandleErrorInfo

<h1>Application Error</h1>
@if (Model != null)
{
    <div>
        Location: @Model.ControllerName/@Model.ActionName
    <br />
        Message: @Model.Exception.Message
    </div>
}
else
{
    <div>
        You've reached this page in error.
    </div>
}