【问题标题】:Entity Framework Code First Migration during deploy to production host does not work部署到生产主机期间的实体框架代码优先迁移不起作用
【发布时间】:2014-01-31 11:46:09
【问题描述】:

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

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

当我部署带有“执行代码优先迁移”复选框的 ASP.Net MVC 应用程序时,该应用程序会在托管服务器上引发 500 错误。

对可能出现的问题有任何想法吗?

【问题讨论】:

  • 你能从服务器得到错误吗? EFCF 迁移在上下文初始化时运行,因此如果出现错误,它们可能不会运行;或者,它们可能是原因。手动更改架构不是一个很好的解决方法,因为它会阻止迁移以后运行(“表 Foo 已经存在”类型错误)。
  • 我还不能得到确切的错误。如果我删除“执行代码优先迁移”,错误就会消失,所以我认为它与初始化有关。
  • 设置一个全局错误处理程序(控制器),在视图中显示错误描述。视图将键入@model System.Web.Mvc.HandleErrorInfo。并显示@Model.Exception.Message。这样您将看到 EF 发出的确切错误消息。
  • 我理解您声明的视图部分,但我对将控制器设置为全局错误处理程序有点不清楚。您可以给我任何示例或进一步说明吗?我目前在项目上安装和配置了 Elmah,但无法从中得到任何响应。谢谢
  • 好的,我会在几分钟后发布答案..

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


【解决方案1】:

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

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

对于 EFCF 迁移,情况并非如此。 VS 的部署将修改您的 web.config 以设置数据库所需的连接字符串。这反映在已发布的文件中,但尚未触及数据库。在迁移代码运行之前,不会对数据库进行更改。这在您的代码第一次初始化 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 错误的原因。

【讨论】:

  • 我确信 DbInitializer 会出现错误。我没有对表或数据库进行任何手动更改。事实上,数据库完全没有我的任何表。
  • @Jimmy stackoverflow.com/questions/65739543/… 你能回答类似的问题吗?
【解决方案2】:

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

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

我不确定为什么在部署事物时会发生转换,但转换不完整。

【讨论】:

  • 啊,棘手。添加该部分以设置 DbInitializer 以使迁移能够运行。这就是 VS 如何确保初始化程序对于迁移是正确的,而不是使用您可能为本地开发启用的 DropAndCreateAlways。
  • 有趣的是,注册该部分应该是安装 EF nugget 包的一部分。你是通过 Nuget 安装的吗?
  • 是的,通过 Nuget。我将从头开始尝试几个 hello world 项目,看看问题是否仍然存在。
  • 尝试了几个 hello world 项目,并自动添加了相应的部分,因此问题似乎是异常的。
  • 我不理解“添加部分描述符”,但代码、分步说明或添加“部分描述符”的链接会为您赢得我的支持。我能够通过重新安装 EF(这是一个痛苦的过程)来解决我的问题,现在它可以工作了。
【解决方案3】:

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

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>
}

【讨论】:

  • 好的,现在对我来说很有意义。谢谢
  • 好的,已经添加了这个并在本地逐步查看它是否有效。我部署到我的托管服务器上,它仍然抛出一个 500 服务器错误,我从来没有得到这个代码。
  • 听起来像是在应用程序运行之前发生了错误。可能是 IIS 配置或 Web.config 错误?另外,您能否检查一下EntityFramework.SqlServer.dll 是否包含在您的部署包中。我最近在发布应用程序时遇到了一个问题,由于某种原因(我使用的是 EF 6.0.1),这个 .dll 不会被包含在内。
猜你喜欢
  • 2012-06-06
  • 2015-07-24
  • 2013-12-29
  • 2013-07-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多