使用 Visual Studio ASP.NET Web 部署:准备数据库部署

下载初学者项目

本系列教程介绍如何使用 Visual Studio 2012 或 Visual Studio 2010 (将) ASP.NET Web 应用程序部署到Azure 应用服务 Web 应用或第三方托管提供程序。 有关该系列的信息,请参阅 该系列中的第一个教程

概述

本教程介绍如何使项目准备好进行数据库部署。 数据库结构和某些 (应用程序两个数据库中数据的所有) 都必须部署到测试、暂存和生产环境。

通常,在开发应用程序时,将测试数据输入到不希望部署到实时站点的数据库中。 但是,你可能还有一些想要部署的生产数据。 在本教程中,你将配置 Contoso University 项目并准备 SQL 脚本,以便在部署时包含正确的数据。

提醒:如果在完成本教程时收到错误消息或某些内容不起作用,请务必检查故障排除页面

SQL Server Express LocalDB

示例应用程序使用 SQL Server Express LocalDB。 SQL Server Express是SQL Server的免费版本。 它通常在开发过程中使用,因为它基于与完整版SQL Server相同的数据库引擎。 可以使用 SQL Server Express 进行测试,并确保应用程序在生产环境中的行为相同,但对于不同版本SQL Server的功能,有一些例外。

LocalDB 是SQL Server Express的特殊执行模式,可用于将数据库作为 .mdf 文件处理。 通常,LocalDB 数据库文件保存在 Web 项目的 App_Data 文件夹中。 SQL Server Express 中的用户实例功能也使你能够处理 .mdf 文件,但用户实例功能已弃用;因此,建议使用 LocalDB 来处理 .mdf 文件。

通常,SQL Server Express不用于生产 Web 应用程序。 特别建议不要将 LocalDB 用于 Web 应用程序,因为它不是设计用于 IIS 的。

在 Visual Studio 2012 中,LocalDB 默认随 Visual Studio 一起安装。 在 Visual Studio 2010 及更早版本中,默认情况下会随 Visual Studio 一起安装没有 LocalDB) 的SQL Server Express (;这就是你将其作为本系列第一个教程中的先决条件之一安装的原因。

有关 SQL Server 版本(包括 LocalDB)的详细信息,请参阅以下资源使用 SQL Server 数据库

实体框架和通用提供程序

对于数据库访问,Contoso University 应用程序需要以下软件,这些软件必须随应用程序一起部署,因为它不包含在.NET Framework中:

由于此软件包含在 NuGet 包中,因此项目已设置好,以便随项目一起部署所需的程序集。 (链接指向这些包的当前版本,这些包可能比为本教程下载的初学者项目中安装的版本更新。)

如果要部署到第三方托管提供程序而不是 Azure,请确保使用 Entity Framework 5.0 或更高版本。 早期版本的 Code First 迁移 需要完全信任,并且大多数托管提供程序将在中等信任中运行应用程序。 有关中等信任的详细信息,请参阅 部署到 IIS 作为测试环境 教程。

为应用程序数据库部署配置Code First 迁移

Contoso University 应用程序数据库由 Code First 管理,你将使用 Code First 迁移 进行部署。 有关使用 Code First 迁移 进行数据库部署的概述,请参阅本系列中的第一个教程

部署应用程序数据库时,通常不会简单地将包含所有数据的开发数据库部署到生产环境,因为其中的大部分数据可能仅用于测试目的。 例如,测试数据库中的学生姓名是虚构的。 另一方面,通常不能只部署没有任何数据的数据库结构。 测试数据库中的某些数据可能是真实数据,当用户开始使用应用程序时必须存在。 例如,数据库可能有一个包含有效成绩值或真实部门名称的表。

为了模拟此常见方案,你将配置一个 Code First 迁移 Seed 方法,该方法仅将希望在生产环境中的数据插入到数据库中。 此方法 Seed 不应插入测试数据,因为它将在 Code First 在生产中创建数据库后在生产环境中运行。

在发布迁移之前的早期版本的 Code First 中,插入测试数据的方法也很常见 Seed ,因为在开发过程中,每次模型更改都必须从头开始完全删除并重新创建数据库。 使用 Code First 迁移,测试数据在数据库更改后保留,因此不需要在 方法中包含Seed测试数据。 下载的项目使用 在初始值设定项类的 方法中包含 Seed 所有数据的 方法。 在本教程中,你将禁用该初始值设定项类并启用迁移。 然后,你将更新 Seed Migrations 配置类中的 方法,以便它仅插入要在生产环境中插入的数据。

下图演示了应用程序数据库的架构:

School_database_diagram

对于这些教程,你将假定 首次部署站点时, StudentEnrollment 表应为空。 其他表包含必须在应用程序上线时预加载的数据。

禁用初始值设定项

由于将使用 Code First 迁移,因此不必使用 DropCreateDatabaseIfModelChanges Code First 初始值设定项。 此初始值设定项的代码位于 ContosoUniversity.DAL 项目的 SchoolInitializer.cs 文件中。 Web.config 文件的 元素中的appSettings设置会导致每当应用程序首次尝试访问数据库时运行此初始值设定项:

<appSettings>
  <add key="Environment" value="Dev" />
  <add key="DatabaseInitializerForType ContosoUniversity.DAL.SchoolContext, ContosoUniversity.DAL" value="ContosoUniversity.DAL.SchoolInitializer, ContosoUniversity.DAL" />
</appSettings>

打开应用程序Web.config文件,删除或注释掉add指定 Code First 初始值设定项类的 元素。 元素 appSettings 现在如下所示:

<appSettings>
  <add key="Environment" value="Dev" />
</appSettings>

注意

指定初始值设定项类的另一种方法是在 Global.asax 文件的 方法中Application_Start调用 Database.SetInitializer 。 如果要在使用该方法指定初始值设定项的项目中启用迁移,请删除该代码行。

注意

如果使用 Visual Studio 2013,请在步骤 2 和 3 之间添加以下步骤: () 在 PMC 中输入“update-package entityframework -version 6.1.1”以获取 EF 的当前版本。 然后, (b) 生成项目以获取生成错误列表并修复它们。 删除不再存在的命名空间的 using 语句,右键单击并单击“解析”以在需要它们的位置添加 using 语句,并将 System.Data.EntityState 的出现次数更改为 System.Data.Entity.EntityState。

启用 Code First 迁移

  1. 确保 ContosoUniversity 项目 (不是 ContosoUniversity.DAL) 设置为启动项目。 在“解决方案资源管理器”中,右键单击“ContosoUniversity”项目,然后选择“设置为启动项目”。 Code First 迁移将在启动项目中查找数据库连接字符串。

  2. “工具 ”菜单中,选择“ NuGet 包管理器>包管理器控制台”。

    Selecting_Package_Manager_Console

  3. “包管理器控制台” 窗口的顶部,选择“ContosoUniversity.DAL”作为默认项目,然后在提示符处 PM> 输入“enable-migrations”。

    enable-migrations 命令

    (如果收到错误,指出 无法识别 enable-migrations 命令,请输入命令 update-package EntityFramework -重新安装 ,然后重试。)

    此命令在 ContosoUniversity.DAL 项目中创建 一个 Migrations 文件夹,并在该文件夹中放入两个文件:可用于配置迁移的 Configuration.cs 文件,以及用于创建数据库的第一次迁移的 InitialCreate.cs 文件。

    迁移文件夹

    包管理器控制台“默认项目”下拉列表中选择了 DAL 项目,enable-migrations因为必须在包含 Code First 上下文类的项目中执行命令。 当类位于类库项目中时,Code First 迁移在解决方案的启动项目中查找数据库连接字符串。 在 ContosoUniversity 解决方案中,Web 项目已设置为启动项目。 如果不想将具有连接字符串的项目指定为 Visual Studio 中的启动项目,可以在 PowerShell 命令中指定启动项目。 若要查看命令语法,请输入命令 get-help enable-migrations

    enable-migrations 命令自动创建了第一个迁移,因为数据库已存在。 另一种方法是让迁移创建数据库。 为此,请在启用迁移之前使用服务器资源管理器SQL Server 对象资源管理器删除 ContosoUniversity 数据库。 启用迁移后,通过输入命令“add-migration InitialCreate”手动创建第一个迁移。 然后,可以通过输入命令“update-database”来创建数据库。

设置 Seed 方法

在本教程中,你将通过将代码添加到 Seed Code First 迁移 Configuration 类的 方法来添加固定数据。 Code First 迁移每次迁移后调用 Seed 方法。

Seed由于 方法在每次迁移后运行,因此首次迁移后表中已有数据。 若要处理这种情况, AddOrUpdate 请使用 方法更新已插入的行,或者插入它们(如果尚不存在)。 方法 AddOrUpdate 可能不是方案的最佳选择。 有关详细信息,请参阅 Julie Lerman 博客上的 注意 EF 4.3 AddOrUpdate 方法

  1. 打开 Configuration.cs 文件,将 方法中的 Seed 注释替换为以下代码:

    var instructors = new List<Instructor>
    {   
        new Instructor { FirstMidName = "Kim",     LastName = "Abercrombie", HireDate = DateTime.Parse("1995-03-11"), OfficeAssignment = new OfficeAssignment { Location = "Smith 17" } },
        new Instructor { FirstMidName = "Fadi",    LastName = "Fakhouri",    HireDate = DateTime.Parse("2002-07-06"), OfficeAssignment = new OfficeAssignment { Location = "Gowan 27" } },
        new Instructor { FirstMidName = "Roger",   LastName = "Harui",       HireDate = DateTime.Parse("1998-07-01"), OfficeAssignment = new OfficeAssignment { Location = "Thompson 304" } },
        new Instructor { FirstMidName = "Candace", LastName = "Kapoor",      HireDate = DateTime.Parse("2001-01-15") },
        new Instructor { FirstMidName = "Roger",   LastName = "Zheng",       HireDate = DateTime.Parse("2004-02-12") }
    };
    instructors.ForEach(s => context.Instructors.AddOrUpdate(i => i.LastName, s));
    context.SaveChanges();
    
    var departments = new List<Department>
    {
        new Department { Name = "English",     Budget = 350000, StartDate = DateTime.Parse("2007-09-01"), PersonID = 1 },
        new Department { Name = "Mathematics", Budget = 100000, StartDate = DateTime.Parse("2007-09-01"), PersonID = 2 },
        new Department { Name = "Engineering", Budget = 350000, StartDate = DateTime.Parse("2007-09-01"), PersonID = 3 },
        new Department { Name = "Economics",   Budget = 100000, StartDate = DateTime.Parse("2007-09-01"), PersonID = 4 }
    };
    departments.ForEach(s => context.Departments.AddOrUpdate(d => d.Name, s));
    context.SaveChanges();
    
    var courses = new List<Course>
    {
        new Course { CourseID = 1050, Title = "Chemistry",      Credits = 3, DepartmentID = 3 },
        new Course { CourseID = 4022, Title = "Microeconomics", Credits = 3, DepartmentID = 4 },
        new Course { CourseID = 4041, Title = "Macroeconomics", Credits = 3, DepartmentID = 4 },
        new Course { CourseID = 1045, Title = "Calculus",       Credits = 4, DepartmentID = 2 },
        new Course { CourseID = 3141, Title = "Trigonometry",   Credits = 4, DepartmentID = 2 },
        new Course { CourseID = 2021, Title = "Composition",    Credits = 3, DepartmentID = 1 },
        new Course { CourseID = 2042, Title = "Literature",     Credits = 4, DepartmentID = 1 }
    };
    courses.ForEach(s => context.Courses.AddOrUpdate(s));
    context.SaveChanges();
    
    courses[0].Instructors.Add(instructors[0]);
    courses[0].Instructors.Add(instructors[1]);
    courses[1].Instructors.Add(instructors[2]);
    courses[2].Instructors.Add(instructors[2]);
    courses[3].Instructors.Add(instructors[3]);
    courses[4].Instructors.Add(instructors[3]);
    courses[5].Instructors.Add(instructors[3]);
    courses[6].Instructors.Add(instructors[3]);
    context.SaveChanges();
    
  2. List 引用下有红色波浪线,因为尚未对其命名空间使用 using 语句。 右键单击 的实例之 List 一,单击“ 解析”,然后单击“ 使用 System.Collections.Generic”。

    使用 using 语句解析

    此菜单选择将以下代码添加到 using 文件顶部附近的 语句中。

    using System.Collections.Generic;
    
  3. 按 CTRL-SHIFT-B 生成项目。

项目现已准备好部署 ContosoUniversity 数据库。 部署应用程序后,首次运行应用程序并导航到访问数据库的页面时,Code First 将创建数据库并运行此方法 Seed

注意

将代码添加到 Seed 方法是将固定数据插入数据库的许多方法之一。 另一种方法是将代码添加到 Up 每个迁移类的 和 Down 方法。 UpDown 方法包含实现数据库更改的代码。 你将在 部署数据库更新 教程中看到相关示例。

还可以使用 Sql 方法编写执行 SQL 语句的代码。 例如,如果要将“预算”列添加到“部门”表,并希望在迁移过程中将所有部门预算初始化为 $1,000.00,则可以将以下代码行添加到 Up 该迁移的方法:

Sql("UPDATE Department SET Budget = 1000");

为成员身份数据库部署创建脚本

Contoso University 应用程序使用 ASP.NET 成员身份系统和表单身份验证对用户进行身份验证和授权。 只有具有管理员角色的用户才能访问 “更新额度 ”页。

运行应用程序并单击“ 课程”,然后单击“ 更新学分”。

单击“更新额度”

之所以显示 “登录 ”页,是因为 “更新额度 ”页需要管理权限。

输入 admin 作为用户名,输入 devpwd 作为密码,然后单击“ 登录”。

登录页

此时将显示 “更新额度 ”页。

“更新额度”页

用户和角色信息位于 aspnet-ContosoUniversity 数据库中,该数据库由 Web.config 文件中的 DefaultConnection 连接字符串指定。

此数据库不由 Entity Framework Code First 管理,因此无法使用迁移来部署它。 你将使用 dbDacFx 提供程序部署数据库架构,并将发布配置文件配置为运行将初始数据插入数据库表的脚本。

注意

Visual Studio 2013引入了名为 ASP.NET Identity) 的新 ASP.NET 成员身份系统 (。 新系统使你能够将应用程序和成员资格表保留在同一数据库中,并且可以使用 Code First 迁移 来部署这两个表。 示例应用程序使用早期 ASP.NET 成员身份系统,无法使用 Code First 迁移 进行部署。 部署此成员资格数据库的过程也适用于应用程序需要部署不是由 Entity Framework Code First 创建的SQL Server数据库的任何其他方案。

在这里,你通常不希望在生产环境中获得与开发时相同的数据。 首次部署站点时,通常排除为测试而创建的大多数或全部用户帐户。 因此,下载的项目具有两个成员资格数据库:具有开发用户的 aspnet-ContosoUniversity.mdf 和包含生产用户的 aspnet-ContosoUniversity-Prod.mdf 。 在本教程中,两个数据库中的用户名相同: adminnonadmin。 两个用户在开发数据库中都有密码 devpwd ,在生产数据库中具有 prodpwd

你将将开发用户部署到测试环境,将生产用户部署到过渡和生产环境。 为此,你将在本教程中创建两个 SQL 脚本,一个用于开发,一个用于生产,在后面的教程中,你将配置发布过程以运行它们。

注意

成员资格数据库存储帐户密码的哈希。 若要将帐户从一台计算机部署到另一台计算机,必须确保哈希例程不会在目标服务器上与在源计算机上生成不同的哈希。 使用 ASP.NET 通用提供程序 时,只要不更改默认算法,它们就会生成相同的哈希。 默认算法为 HMACSHA256,在 Web.config 文件中的 machineKey 元素的验证属性中指定。

可以使用 SQL Server Management Studio (SSMS) 或使用第三方工具手动创建数据部署脚本。 本教程的余下部分将介绍如何在 SSMS 中执行此操作,但如果不想安装和使用 SSMS,可以从项目的已完成版本获取脚本,并跳到将脚本存储在解决方案文件夹中的部分。

若要安装 SSMS,请从下载中心安装它:Microsoft SQL Server 2012 Express方法是单击ENU\x64\SQLManagementStudio_x64_ENU.exe或ENU\x86\SQLManagementStudio_x86_ENU.exe。 如果您为系统选择了错误的安装程序,安装将失败,您可以尝试另一个安装程序。

(请注意,这是 600 兆字节的下载。安装可能需要很长时间,并且需要重新启动计算机。)

在 SQL Server 安装中心的第一页上,单击“新建SQL Server独立安装或向现有安装添加功能”,然后按照说明接受默认选项。

创建开发数据库脚本

  1. 运行 SSMS。

  2. “连接到服务器 ”对话框中,输入 (localdb) \v11.0 作为 服务器名称,将 “身份验证” 保留为“ Windows 身份验证”,然后单击“ 连接”。

    SSMS 连接到服务器

  3. “对象资源管理器”窗口中,展开“数据库”,右键单击“aspnet-ContosoUniversity”,单击“任务”,然后单击“生成脚本”。

    SSMS 生成脚本

  4. “生成和发布脚本 ”对话框中,单击“ 设置脚本选项”。

    可以跳过 “选择对象” 步骤,因为默认值为 “编写整个数据库和所有数据库对象的脚本 ”,这是你想要的。

  5. 单击“高级”。

    SSMS 脚本选项

  6. 在“ 高级脚本选项 ”对话框中,向下滚动到 “要编写脚本的数据的类型”,然后单击下拉列表中的“ 仅数据” 选项。

  7. “脚本 USE DATABASE ”更改为 “False”。 USE 语句对于 Azure SQL 数据库无效,且在测试环境中部署到 SQL Server Express 时不需要这些语句。

    仅 SSMS 脚本数据,无 USE 语句

  8. 单击 “确定”

  9. 在“ 生成和发布脚本 ”对话框中,“ 文件名 ”框指定创建脚本的位置。 将解决方案文件夹的路径 (包含 ContosoUniversity.sln 文件的文件夹) ,并将文件名更改为 aspnet-data-dev.sql

  10. 单击“ 下一步 ”转到“ 摘要 ”选项卡,然后再次单击“ 下一步 ”以创建脚本。

    已创建 SSMS 脚本

  11. 单击“完成” 。

创建生产数据库脚本

由于尚未使用生产数据库运行项目,因此尚未将其附加到 LocalDB 实例。 因此,需要先附加数据库。

  1. 在 SSMS 对象资源管理器中,右键单击“数据库”,然后单击“附加”。

    SSMS 附加

  2. 在“附加数据库”对话框中,单击“添加”,然后导航到App_Data文件夹中的 aspnet-ContosoUniversity-Prod.mdf 文件。

    SSMS 添加要附加的 .mdf 文件

  3. 单击 “确定”

  4. 按照前面使用的相同过程为生产文件创建脚本。 将脚本文件命名 为 aspnet-data-prod.sql

总结

这两个数据库现在都可以部署,解决方案文件夹中有两个数据部署脚本。

数据部署脚本

在以下教程中,你将配置影响部署的项目设置,并为部署的应用程序中必须不同的设置设置设置设置自动 Web.config 文件转换。

更多信息

有关 NuGet 的详细信息,请参阅 使用 NuGet 管理项目库NuGet 文档。 如果不想使用 NuGet,则需要了解如何分析 NuGet 包,以确定安装 NuGet 包时它的作用。 (例如,它可以配置Web.config转换、配置 PowerShell 脚本以在生成时运行等) 若要详细了解 NuGet 的工作原理,请参阅创建和发布包和配置文件和源代码转换