教程:在 Azure 应用服务中生成 ASP.NET Core 和 Azure SQL 数据库应用

Azure 应用服务在 Azure 中提供高度可缩放、自修补的 Web 托管服务。 本教程演示如何创建 .NET Core 应用,并将其连接至 SQL 数据库。 完成操作后,将拥有一个在 Windows 应用服务中运行的 .NET Core MVC 应用。

Azure 应用服务使用 Linux 操作系统,提供高度可缩放的自修补 Web 托管服务。 本教程演示如何创建 .NET Core 应用,并将其连接至 SQL 数据库。 完成操作后,将拥有一个在 Linux 应用服务中运行的 .NET Core MVC 应用。

在应用服务中运行的应用

在本教程中,你将了解如何执行以下操作:

  • 在 Azure 中创建 SQL 数据库。
  • 将 .NET Core 应用连接到 SQL 数据库
  • 将应用部署到 Azure
  • 更新数据模型并重新部署应用
  • 从 Azure 流式传输诊断日志
  • 在 Azure 门户中管理应用

如果没有 Azure 订阅,可在开始前创建一个试用帐户

先决条件

完成本教程:

  • 如果需要,请安装 Azure CLI 来运行 CLI 参考命令。

    • 如果使用的是本地安装,请使用 az login 命令登录到 Azure CLI。 若要完成身份验证过程,请遵循终端中显示的步骤。 有关其他登录选项,请参阅登录 Azure CLI

    • 出现提示时,请在首次使用时安装 Azure CLI 扩展。 有关扩展详细信息,请参阅使用 Azure CLI 的扩展

    • 运行 az version 以查找安装的版本和依赖库。 若要升级到最新版本,请运行 az upgrade

创建本地 .NET Core 应用

在此步骤中,你将设置本地 .NET Core 项目。

克隆示例应用程序

在终端窗口中,通过 cd 转到工作目录。

运行以下命令来克隆示例存储库,并转到其根目录。

git clone https://github.com/azure-samples/dotnetcore-sqldb-tutorial
cd dotnetcore-sqldb-tutorial

此示例项目包含使用 Entity Framework Core 的基本 CRUD(创建-读取-更新-删除)应用。

运行应用程序

运行以下命令,安装所需的包,运行数据库迁移并启动应用程序。

dotnet tool install -g dotnet-ef
dotnet ef database update
dotnet run

在浏览器中导航至 http://localhost:5000 。 选择“新建”链接,创建多个待办事项。

已成功连接到 SQL 数据库

在终端按 Ctrl+C,随时停止 .NET Core。

创建生产环境 SQL 数据库

此步骤在 Azure 中创建一个 SQL 数据库。 应用部署到 Azure 后,它将使用该云数据库。

对于 SQL 数据库,本教程使用 Azure SQL 数据库

创建资源组

资源组是在其中部署和管理 Azure 资源(如 Web 应用、数据库和存储帐户)的逻辑容器。 例如,可以选择在使用完之后通过一个简单的步骤删除整个资源组。

在 Azure CLI 中,使用 az group create 命令创建资源组。 以下示例在“中国北部”位置创建名为“myResourceGroup”的资源组。 要查看“免费”层中应用服务支持的所有位置,请运行 az appservice list-locations --sku FREE 命令。

az group create --name myResourceGroup --location "China North"

通常在附近的区域中创建资源组和资源。

此命令完成后,JSON 输出会显示资源组属性。

创建 SQL 数据库逻辑服务器

在 Azure CLI 中,使用 az sql server create 命令创建 SQL 数据库逻辑服务器。

将 <server-name> 占位符替换为唯一的 SQL 数据库名称 。 此名称将用作全局唯一的 SQL 数据库终结点 (<server-name>.database.chinacloudapi.cn) 的一部分。 有效字符为 a-z0-9-。 此外,将 <db-username> 和 <db-password> 替换为所选的用户名和密码 。

az sql server create --name <server-name> --resource-group myResourceGroup --location "China North" --admin-user <db-username> --admin-password <db-password>

创建 SQL 数据库逻辑服务器后,Azure CLI 会显示类似于以下示例的信息:

{
  "administratorLogin": "<db-username>",
  "administratorLoginPassword": null,
  "fullyQualifiedDomainName": "<server-name>.database.chinacloudapi.cn",
  "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myResourceGroup/providers/Microsoft.Sql/servers/<server-name>",
  "identity": null,
  "kind": "v12.0",
  "location": "chinanorth",
  "name": "<server-name>",
  "resourceGroup": "myResourceGroup",
  "state": "Ready",
  "tags": null,
  "type": "Microsoft.Sql/servers",
  "version": "12.0"
}

配置服务器防火墙规则

使用 az sql server firewall create 命令创建 Azure SQL 数据库服务器级防火墙规则。 若同时将起始 IP 和结束 IP 设置为 0.0.0.0,防火墙将仅对其他 Azure 资源开启。

az sql server firewall-rule create --resource-group myResourceGroup --server <server-name> --name AllowAzureIps --start-ip-address 0.0.0.0 --end-ip-address 0.0.0.0

提示

你甚至可以让防火墙规则更严格,即只使用应用所使用的出站 IP 地址

在 Azure CLI 中再次运行该命令(将 <your-ip-address> 替换为本地 IPv4 IP 地址),以便允许从本地计算机进行访问。

az sql server firewall-rule create --name AllowLocalClient --server <server-name> --resource-group myResourceGroup --start-ip-address=<your-ip-address> --end-ip-address=<your-ip-address>

创建数据库

使用 az sql db create 命令在服务器中创建 S0 性能级别的数据库。

az sql db create --resource-group myResourceGroup --server <server-name> --name coreDB --service-objective S0

检索连接字符串

使用 az sql db show-connection-string 命令获取连接字符串。

az sql db show-connection-string --client ado.net --server <server-name> --name coreDB

在命令输出中,将 <username> 和 <password> 替换为你先前使用的数据库管理员凭据 。

这是 .NET Core 应用的连接字符串。 将其进行复制,留待稍后使用。

配置应用以连接到生产数据库

在本地存储库中,打开 Startup.cs 并查找下列代码:

services.AddDbContext<MyDatabaseContext>(options =>
        options.UseSqlite("Data Source=localdatabase.db"));

将其替换为以下代码。

services.AddDbContext<MyDatabaseContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("MyDbConnection")));

重要

对于需要横向扩展的生产应用,请遵循在生产中应用迁移中的最佳做法。

运行到生产数据库的数据库迁移

应用当前连接到本地 Sqlite 数据库。 配置 Azure SQL 数据库后,请重新创建以其为目标的初始迁移。

在存储库根目录中运行以下命令。 将 <connection-string> 替换为之前创建的连接字符串。

# Delete old migrations
rm -r Migrations
# Recreate migrations
dotnet ef migrations add InitialCreate

# Set connection string to production database
# PowerShell
$env:ConnectionStrings:MyDbConnection="<connection-string>"
# CMD (no quotes)
set ConnectionStrings:MyDbConnection=<connection-string>
# Bash (no quotes)
export ConnectionStrings__MyDbConnection=<connection-string>

# Run migrations
dotnet ef database update

使用新配置运行应用

现在,数据库迁移将在生产数据库中运行,请通过运行以下命令来测试应用:

dotnet run

在浏览器中导航至 http://localhost:5000 。 选择“新建”链接,创建多个待办事项。 应用现在正在读取数据并将数据写入生产数据库。

提交本地更改,然后将其提交到 Git 存储库。

git add .
git commit -m "connect to SQLDB in Azure"

现在已准备好部署代码。

将应用部署到 Azure

在此步骤中,将已连接 SQL 数据库的 .NET Core 应用程序部署到应用服务。

配置本地 Git 部署

可以使用“部署用户” 将 FTP 和本地 Git 部署到 Azure Web 应用。 配置部署用户之后,可对所有 Azure 部署使用此用户。 帐户级部署用户名和密码不同于 Azure 订阅凭据。

若要配置部署用户,请在 Azure Cloud Shell 中运行 az webapp deployment user set 命令。 将 <username> 和 <password> 替换为部署用户名和密码。

  • 用户名必须在 Azure 中唯一,并且对于本地 Git 推送,不能包含“@”符号。
  • 密码必须至少为 8 个字符,且具有字母、数字和符号这三种元素中的两种。
az webapp deployment user set --user-name <username> --password <password>

JSON 输出会将该密码显示为 null。 如果收到 'Conflict'. Details: 409 错误,请更改用户名。 如果收到 'Bad Request'. Details: 400 错误,请使用更强的密码。

请记录你要用于部署 Web 应用的用户名和密码。

创建应用服务计划

使用 az appservice plan create 命令创建应用服务计划。

以下示例在免费定价层中创建名为 myAppServicePlan 的应用服务计划:

az appservice plan create --name myAppServicePlan --resource-group myResourceGroup --sku FREE

创建应用服务计划后,Azure CLI 会显示类似于以下示例的信息:

{ 
  "adminSiteName": null,
  "appServicePlanName": "myAppServicePlan",
  "geoRegion": "China North",
  "hostingEnvironmentProfile": null,
  "id": "/subscriptions/0000-0000/resourceGroups/myResourceGroup/providers/Microsoft.Web/serverfarms/myAppServicePlan",
  "kind": "app",
  "location": "China North",
  "maximumNumberOfWorkers": 1,
  "name": "myAppServicePlan",
  < JSON data removed for brevity. >
  "targetWorkerSizeId": 0,
  "type": "Microsoft.Web/serverfarms",
  "workerTierName": null
} 

在 Azure CLI 中,使用 az appservice plan create 命令创建一个应用服务计划。

以下示例在免费定价层中创建名为 myAppServicePlan 的应用服务计划:

az appservice plan create --name myAppServicePlan --resource-group myResourceGroup --sku FREE

创建应用服务计划后,Azure CLI 会显示类似于以下示例的信息:

{ 
  "adminSiteName": null,
  "appServicePlanName": "myAppServicePlan",
  "geoRegion": "China North",
  "hostingEnvironmentProfile": null,
  "id": "/subscriptions/0000-0000/resourceGroups/myResourceGroup/providers/Microsoft.Web/serverfarms/myAppServicePlan",
  "kind": "app",
  "location": "China North",
  "maximumNumberOfWorkers": 1,
  "name": "myAppServicePlan",
  < JSON data removed for brevity. >
  "targetWorkerSizeId": 0,
  "type": "Microsoft.Web/serverfarms",
  "workerTierName": null
} 

创建 Web 应用

myAppServicePlan 应用服务计划中创建一个 Web 应用

在 Azure CLI 中,可以使用 az webapp create 命令。 在以下示例中,将 <app-name> 替换为全局唯一的应用名称(有效字符是 a-z0-9-)。

az webapp create --resource-group myResourceGroup --plan myAppServicePlan --name <app-name> --deployment-local-git

创建 Web 应用后,Azure CLI 会显示类似于以下示例的输出:

Local git is configured with url of 'https://<username>@<app-name>.scm.chinacloudsites.cn/<app-name>.git'
{
  "availabilityState": "Normal",
  "clientAffinityEnabled": true,
  "clientCertEnabled": false,
  "clientCertExclusionPaths": null,
  "cloningInfo": null,
  "containerSize": 0,
  "dailyMemoryTimeQuota": 0,
  "defaultHostName": "<app-name>.chinacloudsites.cn",
  "deploymentLocalGitUrl": "https://<username>@<app-name>.scm.chinacloudsites.cn/<app-name>.git",
  "enabled": true,
  < JSON data removed for brevity. >
}

备注

Git 远程的 URL 将显示在 deploymentLocalGitUrl 属性中,其格式为 https://<username>@<app-name>.scm.chinacloudsites.cn/<app-name>.git。 保存此 URL,后续将会用到。

myAppServicePlan 应用服务计划中创建一个 Web 应用

在 Azure CLI 中,可以使用 az webapp create 命令。 在以下示例中,将 <app-name> 替换为全局唯一的应用名称(有效字符是 a-z0-9-)。 运行时设置为 DOTNETCORE|3.1。 若要查看所有受支持的运行时,请运行 az webapp list-runtimes --linux

# Bash
az webapp create --resource-group myResourceGroup --plan myAppServicePlan --name <app-name> --runtime "DOTNETCORE|3.1" --deployment-local-git
# PowerShell
az --% webapp create --resource-group myResourceGroup --plan myAppServicePlan --name <app-name> --runtime "DOTNETCORE|3.1" --deployment-local-git

创建 Web 应用后,Azure CLI 会显示类似于以下示例的输出:

Local git is configured with url of 'https://<username>@<app-name>.scm.chinacloudsites.cn/<app-name>.git'
{
  "availabilityState": "Normal",
  "clientAffinityEnabled": true,
  "clientCertEnabled": false,
  "cloningInfo": null,
  "containerSize": 0,
  "dailyMemoryTimeQuota": 0,
  "defaultHostName": "<app-name>.chinacloudsites.cn",
  "deploymentLocalGitUrl": "https://<username>@<app-name>.scm.chinacloudsites.cn/<app-name>.git",
  "enabled": true,
  < JSON data removed for brevity. >
}

已在 Linux 容器中创建了空的 Web 应用并启用了 Git 部署。

备注

Git 远程的 URL 将显示在 deploymentLocalGitUrl 属性中,其格式为 https://<username>@<app-name>.scm.chinacloudsites.cn/<app-name>.git。 保存此 URL,后续将会用到。

配置连接字符串

若要为 Azure 应用设置连接字符串,请在 Azure CLI 中使用 az webapp config appsettings set 命令。 在下列命令中,将 <app name> 和 <connection-string> 参数替换为先前创建的连接字符串 。

az webapp config connection-string set --resource-group myResourceGroup --name <app-name> --settings MyDbConnection="<connection-string>" --connection-string-type SQLAzure

在 ASP.NET Core 中,可以通过标准模式使用此命名连接字符串 (MyDbConnection),就像在 appsettings.json 中指定的任何连接字符串一样。 在本例中,MyDbConnection 也在 appsettings.json 中定义。 在应用服务中运行时,应用服务中定义的连接字符串优先于 appsettings.json 中定义的连接字符串。 此代码在本地开发过程中使用 appsettings.json 值,相同的代码在部署时使用应用服务值。

若要了解如何在代码中引用连接字符串,请参阅配置应用以连接到生产数据库

从 Git 推送到 Azure

回到本地终端窗口,将 Azure 远程功能添加到本地 Git 存储库。 将 <deploymentLocalGitUrl-from-create-step> 替换为在创建 Web 应用中保存的 Git 远程 URL。

git remote add azure <deploymentLocalGitUrl-from-create-step>

使用以下命令推送到 Azure 远程库以部署应用。 当 Git 凭据管理器提示输入凭据时,请确保输入在 配置部署用户 中创建的凭据,而不是用于登录到 Azure 门户的凭据。

git push azure master

此命令可能需要花费几分钟时间运行。 运行时,该命令会显示类似于以下示例的信息:

Enumerating objects: 268, done.
Counting objects: 100% (268/268), done.
Compressing objects: 100% (171/171), done.
Writing objects: 100% (268/268), 1.18 MiB | 1.55 MiB/s, done.
Total 268 (delta 95), reused 251 (delta 87), pack-reused 0
remote: Resolving deltas: 100% (95/95), done.
remote: Updating branch 'main'.
remote: Updating submodules.
remote: Preparing deployment for commit id '64821c3558'.
remote: Generating deployment script.
remote: Project file path: .\DotNetCoreSqlDb.csproj
remote: Generating deployment script for ASP.NET MSBuild16 App
remote: Generated deployment script files
remote: Running deployment command...
remote: Handling ASP.NET Core Web Application deployment with MSBuild16.
remote: .
remote: .
remote: .
remote: Finished successfully.
remote: Running post deployment command(s)...
remote: Triggering recycle (preview mode disabled).
remote: App container will begin restart within 10 seconds.
To https://<app-name>.scm.chinacloudsites.cn/<app-name>.git
 * [new branch]      main -> main

回到本地终端窗口,将 Azure 远程功能添加到本地 Git 存储库。 将 <deploymentLocalGitUrl-from-create-step> 替换为在创建 Web 应用中保存的 Git 远程 URL。

git remote add azure <deploymentLocalGitUrl-from-create-step>

使用以下命令推送到 Azure 远程库以部署应用。 当 Git 凭据管理器提示输入凭据时,请确保输入在 配置部署用户 中创建的凭据,而不是用于登录到 Azure 门户的凭据。

git push azure master

此命令可能需要花费几分钟时间运行。 运行时,该命令会显示类似于以下示例的信息:

Enumerating objects: 273, done.
Counting objects: 100% (273/273), done.
Delta compression using up to 4 threads
Compressing objects: 100% (175/175), done.
Writing objects: 100% (273/273), 1.19 MiB | 1.85 MiB/s, done.
Total 273 (delta 96), reused 259 (delta 88)
remote: Resolving deltas: 100% (96/96), done.
remote: Deploy Async
remote: Updating branch 'main'.
remote: Updating submodules.
remote: Preparing deployment for commit id 'cccecf86c5'.
remote: Repository path is /home/site/repository
remote: Running oryx build...
remote: Build orchestrated by Microsoft Oryx, https://github.com/Microsoft/Oryx
remote: You can report issues at https://github.com/Microsoft/Oryx/issues
remote: .
remote: .
remote: .
remote: Done.
remote: Running post deployment command(s)...
remote: Triggering recycle (preview mode disabled).
remote: Deployment successful.
remote: Deployment Logs : 'https://<app-name>.scm.chinacloudsites.cn/newui/jsonviewer?view_url=/api/deployments/cccecf86c56493ffa594e76ea1deb3abb3702d89/log'
To https://<app-name>.scm.chinacloudsites.cn/<app-name>.git
 * [new branch]      main -> main

转到 Azure 应用

使用 Web 浏览器转到已部署的应用。

http://<app-name>.chinacloudsites.cn

添加多个待办事项。

在应用服务中运行的应用

祝贺你! 数据驱动的 .NET Core 应用已经在你的应用服务中运行了。

在本地更新并重新部署

在此步骤中,将对数据库架构做出更改,并将其发布至 Azure。

更新数据模型

在代码编辑器中打开 Models/Todo.cs。 将以下属性添加到 ToDo 类:

public bool Done { get; set; }

重新运行数据库迁移

运行几个命令以更新生产数据库。

dotnet ef migrations add AddProperty
dotnet ef database update

备注

如果打开新的终端窗口,则需要像在运行到生产数据库的数据库迁移中一样,在终端中将连接字符串设置为生产数据库。

使用新属性

为了使用 Done 属性,请对代码做一些更改。 简单起见,本教程中将仅更改 IndexCreate 视图,以便在操作过程中查看属性。

打开 Controllers/TodosController.cs。

找到 Create([Bind("ID,Description,CreatedDate")] Todo todo) 方法,并将 Done 添加到 Bind 属性中的属性列表。 完成后,Create() 方法签名应如下面的代码所示:

public async Task<IActionResult> Create([Bind("ID,Description,CreatedDate,Done")] Todo todo)

打开 Views/Todos/Create.cshtml。

在 Razor 代码中,应能看到用于 Description<div class="form-group"> 元素,以及另一个用于 CreatedDate<div class="form-group"> 元素。 紧跟在这两个元素之后,添加另一个用于 Done<div class="form-group"> 元素:

<div class="form-group">
    <label asp-for="Done" class="col-md-2 control-label"></label>
    <div class="col-md-10">
        <input asp-for="Done" class="form-control" />
        <span asp-validation-for="Done" class="text-danger"></span>
    </div>
</div>

打开 Views/Todos/Index.cshtml。

搜索空的 <th></th> 元素。 在此元素的正上方,添加下列 Razor 代码:

<th>
    @Html.DisplayNameFor(model => model.Done)
</th>

查找包含 asp-action 标记帮助程序的 <td> 元素。 在此元素的正上方,添加下列 Razor 代码:

<td>
    @Html.DisplayFor(modelItem => item.Done)
</td>

这就是要在 IndexCreate 视图中查看更改所需的全部操作。

在本地测试更改

在本地运行应用。

dotnet run

备注

如果打开新的终端窗口,则需要像在运行到生产数据库的数据库迁移中一样,在终端中将连接字符串设置为生产数据库。

在浏览器中,导航到 http://localhost:5000/。 你现在可以添加一个待办事项,并检查''Done''。 然后,它应作为已完成项在主页中显示。 请记住,Edit视图不显示Done字段,因为没有更改Edit视图。

发布对 Azure 所做的更改

git add .
git commit -m "added done field"
git push azure main

git push 完成后,请导航至应用服务应用,尝试添加一个待办事项并选中“Done”。

Code First 迁移后的 Azure 应用

所有现有待办事项仍将显示。 重新发布 ASP.NET Core 应用时,SQL 数据库中的现有数据不会丢失。 此外,实体框架核心迁移仅更改数据架构,而使现有数据保持不变。

流式传输诊断日志

当 ASP.NET Core 应用在 Azure 应用服务中运行时,可以将控制台日志通过管道传输到 Azure CLI。 如此,可以获得相同的诊断消息,以便调试应用程序错误。

示例项目已遵循了 Azure 中的 ASP.NET Core 日志记录中的指南,并且进行了两个配置更改:

  • DotNetCoreSqlDb.csproj 中包含了对 Microsoft.Extensions.Logging.AzureAppServices 的引用。
  • Program.cs 中调用 loggerFactory.AddAzureWebAppDiagnostics()

若要将应用服务中的 ASP.NET Core 日志级别从默认级别 Error 设置为 Information,请在 Azure CLI 中使用 az webapp log config 命令。

az webapp log config --name <app-name> --resource-group myResourceGroup --application-logging filesystem --level information

备注

项目的日志级别在 appsettings.json 中已设置为 Information

若要启动日志流式处理,请在 Azure CLI 中使用 az webapp log tail 命令。

az webapp log tail --name <app-name> --resource-group myResourceGroup

启动日志流式处理后,请在浏览器中刷新 Azure 应用,以获取一些 Web 流量。 现在可以看到通过管道传送到终端的控制台日志。 如果没有立即看到控制台日志,请在 30 秒后重新查看。

若要随时停止日志流式处理,请键入 Ctrl+C

有关自定义 ASP.NET Core 日志的详细信息,请参阅 ASP.NET Core 中的日志记录

管理 Azure 应用

若要查看所创建的应用,请在 Azure 门户中,搜索并选择“应用服务”"。

在 Azure 门户中选择应用服务

在“应用服务”页上,选择 Azure 应用的名称。

在门户中导航到 Azure 应用

默认情况下,门户将显示应用的“概述”页。 在此页中可以查看应用的运行状况。 在此处还可以执行基本的管理任务,例如浏览、停止、启动、重新启动和删除。 该页左侧的选项卡显示可以打开的不同配置页。

Azure 门户中的“应用服务”页

清理资源

若要删除通过此快速入门创建的所有资源,请运行以下命令:

az group delete --name myResourceGroup

后续步骤

你已了解:

  • 在 Azure 中创建 SQL 数据库。
  • 将 .NET Core 应用连接到 SQL 数据库
  • 将应用部署到 Azure
  • 更新数据模型并重新部署应用
  • 将日志从 Azure 流式传输到终端
  • 在 Azure 门户中管理应用

继续学习下一篇教程,了解如何将自定义 DNS 名称映射到应用。

或者,查看其他资源: