Skip to content

Commit 8a37136

Browse files
committed
update core+sqldb tutorials
1 parent be6b897 commit 8a37136

File tree

4 files changed

+238
-181
lines changed

4 files changed

+238
-181
lines changed

articles/app-service/app-service-web-tutorial-dotnetcore-sqldb.md

Lines changed: 107 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ description: Learn how to get a .NET Core app working in Azure App Service, with
44

55
ms.devlang: dotnet
66
ms.topic: tutorial
7-
ms.date: 08/06/2019
7+
ms.date: 04/23/2020
88
ms.custom: mvc, cli-validate, seodec18
99
---
1010

@@ -18,7 +18,7 @@ ms.custom: mvc, cli-validate, seodec18
1818

1919
![app running in App Service](./media/app-service-web-tutorial-dotnetcore-sqldb/azure-app-in-browser.png)
2020

21-
What you learn how to:
21+
In this tutorial, you learn how to:
2222

2323
> [!div class="checklist"]
2424
> * Create a SQL Database in Azure
@@ -34,8 +34,8 @@ What you learn how to:
3434

3535
To complete this tutorial:
3636

37-
* [Install Git](https://git-scm.com/)
38-
* [Install .NET Core SDK](https://dotnet.microsoft.com/download)
37+
* <a href="https://git-scm.com/" target="_blank">Install Git</a>
38+
* <a href="https://dotnet.microsoft.com/download/dotnet-core/3.1" target="_blank">Install the latest .NET Core 3.1 SDK</a>
3939

4040
## Create local .NET Core app
4141

@@ -59,8 +59,8 @@ The sample project contains a basic CRUD (create-read-update-delete) app using [
5959
Run the following commands to install the required packages, run database migrations, and start the application.
6060

6161
```bash
62-
dotnet tool install -g dotnet-ef --version 3.1.1
63-
dotnet-ef database update
62+
dotnet tool install -g dotnet-ef
63+
dotnet ef database update
6464
dotnet run
6565
```
6666

@@ -86,25 +86,25 @@ For SQL Database, this tutorial uses [Azure SQL Database](/azure/sql-database/).
8686

8787
In the Cloud Shell, create a SQL Database logical server with the [`az sql server create`](/cli/azure/sql/server?view=azure-cli-latest#az-sql-server-create) command.
8888

89-
Replace the *\<server_name>* placeholder with a unique SQL Database name. This name is used as the part of the SQL Database endpoint, `<server_name>.database.windows.net`, so the name needs to be unique across all logical servers in Azure. The name must contain only lowercase letters, numbers, and the hyphen (-) character, and must be between 3 and 50 characters long. Also, replace *\<db_username>* and *\<db_password>* with a username and password of your choice.
89+
Replace the *\<server-name>* placeholder with a *unique* SQL Database name. This name is used as the part of the globally unique SQL Database endpoint, `<server-name>.database.windows.net`. Valid characters are `a`-`z`, `0`-`9`, `-`. Also, replace *\<db-username>* and *\<db-password>* with a username and password of your choice.
9090

9191

9292
```azurecli-interactive
93-
az sql server create --name <server_name> --resource-group myResourceGroup --location "West Europe" --admin-user <db_username> --admin-password <db_password>
93+
az sql server create --name <server-name> --resource-group myResourceGroup --location "West Europe" --admin-user <db-username> --admin-password <db-password>
9494
```
9595

9696
When the SQL Database logical server is created, the Azure CLI shows information similar to the following example:
9797

9898
<pre>
9999
{
100-
"administratorLogin": "&lt;db_username&gt;",
100+
"administratorLogin": "&lt;db-username&gt;",
101101
"administratorLoginPassword": null,
102-
"fullyQualifiedDomainName": "&lt;server_name&gt;.database.windows.net",
103-
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myResourceGroup/providers/Microsoft.Sql/servers/&lt;server_name&gt;",
102+
"fullyQualifiedDomainName": "&lt;server-name&gt;.database.windows.net",
103+
"id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/myResourceGroup/providers/Microsoft.Sql/servers/&lt;server-name&gt;",
104104
"identity": null,
105105
"kind": "v12.0",
106106
"location": "westeurope",
107-
"name": "&lt;server_name&gt;",
107+
"name": "&lt;server-name&gt;",
108108
"resourceGroup": "myResourceGroup",
109109
"state": "Ready",
110110
"tags": null,
@@ -118,137 +118,158 @@ When the SQL Database logical server is created, the Azure CLI shows information
118118
Create an [Azure SQL Database server-level firewall rule](../sql-database/sql-database-firewall-configure.md) using the [`az sql server firewall create`](/cli/azure/sql/server/firewall-rule?view=azure-cli-latest#az-sql-server-firewall-rule-create) command. When both starting IP and end IP are set to 0.0.0.0, the firewall is only opened for other Azure resources.
119119

120120
```azurecli-interactive
121-
az sql server firewall-rule create --resource-group myResourceGroup --server <server_name> --name AllowAllIps --start-ip-address 0.0.0.0 --end-ip-address 0.0.0.0
121+
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
122122
```
123123

124124
> [!TIP]
125125
> You can be even more restrictive in your firewall rule by [using only the outbound IP addresses your app uses](overview-inbound-outbound-ips.md#find-outbound-ips).
126126
>
127127
128+
In the Cloud Shell, run the command again to allow access from your local computer by replacing *\<your-ip-address>* with [your local IPv4 IP address](https://www.whatsmyip.org/).
129+
130+
```azurecli-interactive
131+
az sql server firewall-rule create --name AllowLocalClient --server <mysql_server_name> --resource-group myResourceGroup --start-ip-address=<your-ip-address> --end-ip-address=<your-ip-address>
132+
```
133+
128134
### Create a database
129135

130136
Create a database with an [S0 performance level](../sql-database/sql-database-service-tiers-dtu.md) in the server using the [`az sql db create`](/cli/azure/sql/db?view=azure-cli-latest#az-sql-db-create) command.
131137

132138
```azurecli-interactive
133-
az sql db create --resource-group myResourceGroup --server <server_name> --name coreDB --service-objective S0
139+
az sql db create --resource-group myResourceGroup --server <server-name> --name coreDB --service-objective S0
134140
```
135141

136142
### Create connection string
137143

138-
Replace the following string with the *\<server_name>*, *\<db_username>*, and *\<db_password>* you used earlier.
144+
Get the connection string using the [`az sql db show-connection-string`](/cli/azure/sql/db?view=azure-cli-latest#az-sql-db-show-connection-string) command.
139145

146+
```azurecli-interactive
147+
az sql db show-connection-string --client ado.net --server cephalin-core --name coreDB
140148
```
141-
Server=tcp:<server_name>.database.windows.net,1433;Database=coreDB;User ID=<db_username>;Password=<db_password>;Encrypt=true;Connection Timeout=30;
142-
```
149+
150+
In the command output, replace *\<username>*, and *\<password>* with the database administrator credentials you used earlier.
143151

144152
This is the connection string for your .NET Core app. Copy it for use later.
145153

146-
## Deploy app to Azure
154+
### Configure app to connect to production database
147155

148-
In this step, you deploy your SQL Database-connected .NET Core application to App Service.
149-
150-
### Configure local git deployment
156+
In your local repository, open Startup.cs and find the following code:
151157

152-
[!INCLUDE [Configure a deployment user](../../includes/configure-deployment-user-no-h.md)]
158+
```csharp
159+
services.AddDbContext<MyDatabaseContext>(options =>
160+
options.UseSqlite("Data Source=localdatabase.db"));
161+
```
153162

154-
### Create an App Service plan
163+
Replace it with the following code.
155164

156-
[!INCLUDE [Create app service plan](../../includes/app-service-web-create-app-service-plan-no-h.md)]
165+
```csharp
166+
services.AddDbContext<MyDatabaseContext>(options =>
167+
options.UseSqlServer(Configuration.GetConnectionString("MyDbConnection")));
168+
```
157169

158-
### Create a web app
170+
> [!IMPORTANT]
171+
> For production apps that need to scale out, follow the best practices in [Applying migrations in production](/aspnet/core/data/ef-rp/migrations#applying-migrations-in-production).
172+
>
159173
160-
[!INCLUDE [Create web app](../../includes/app-service-web-create-web-app-dotnetcore-win-no-h.md)]
174+
### Run database migrations to the production database
161175

162-
### Configure connection string
176+
Your app currently connects to a local Sqlite database. Now that you configured an Azure SQL Database, recreate the initial migration to target it.
163177

164-
To set connection strings for your Azure app, use the [`az webapp config appsettings set`](/cli/azure/webapp/config/appsettings?view=azure-cli-latest#az-webapp-config-appsettings-set) command in the Cloud Shell. In the following command, replace *\<app name>*, as well as the *\<connection_string>* parameter with the connection string you created earlier.
178+
From the repository root, run the following commands. Replace *\<connection-string>* with the connection string you created earlier.
165179

166-
```azurecli-interactive
167-
az webapp config connection-string set --resource-group myResourceGroup --name <app name> --settings MyDbConnection="<connection_string>" --connection-string-type SQLServer
180+
```
181+
# Delete old migrations
182+
rm Migrations -r
183+
# Recreate migrations
184+
dotnet ef migrations add InitialCreate
185+
186+
# Set connection string to production database
187+
# PowerShell
188+
$env:ConnectionStrings:MyDbConnection="<connection-string>"
189+
# CMD (no quotes)
190+
set ConnectionStrings:MyDbConnection=<connection-string>
191+
# Bash (no quotes)
192+
export ConnectionStrings__MyDbConnection=<connection-string>
193+
194+
# Run migrations
195+
dotnet ef database update
168196
```
169197

170-
In ASP.NET Core, you can use this named connection string (`MyDbConnection`) using the standard pattern, like any connection string specified in *appsettings.json*. In this case, `MyDbConnection` is also defined in your *appsettings.json*. When running in App Service, the connection string defined in App Service takes precedence over the connection string defined in your *appsettings.json*. The code uses the *appsettings.json* value during local development, and the same code uses the App Service value when deployed.
198+
### Run app with new configuration
171199

172-
To see how the connection string is referenced in your code, see [Connect to SQL Database in production](#connect-to-sql-database-in-production).
200+
Now that database migrations is run on the production database, test your app by running:
173201

174-
### Configure environment variable
202+
```
203+
dotnet run
204+
```
175205

176-
Next, set `ASPNETCORE_ENVIRONMENT` app setting to _Production_. This setting lets you know whether you're running in Azure, because you use SQLite for your local development environment and SQL Database for your Azure environment.
206+
Navigate to `http://localhost:5000` in a browser. Select the **Create New** link and create a couple _to-do_ items. Your app is now reading and writing data to the production database.
177207

178-
The following example configures a `ASPNETCORE_ENVIRONMENT` app setting in your Azure app. Replace the *\<app_name>* placeholder.
208+
Commit your local changes, then commit it into your Git repository.
179209

180-
```azurecli-interactive
181-
az webapp config appsettings set --name <app_name> --resource-group myResourceGroup --settings ASPNETCORE_ENVIRONMENT="Production"
210+
```bash
211+
git add .
212+
git commit -m "connect to SQLDB in Azure"
182213
```
183214

184-
To see how the environment variable is referenced in your code, see [Connect to SQL Database in production](#connect-to-sql-database-in-production).
215+
You're now ready to deploy your code.
185216

186-
### Connect to SQL Database in production
217+
## Deploy app to Azure
187218

188-
In your local repository, open Startup.cs and find the following code:
219+
In this step, you deploy your SQL Database-connected .NET Core application to App Service.
189220

190-
```csharp
191-
services.AddDbContext<MyDatabaseContext>(options =>
192-
options.UseSqlite("Data Source=localdatabase.db"));
193-
```
221+
### Configure local git deployment
194222

195-
Replace it with the following code, which uses the environment variables that you configured earlier.
223+
[!INCLUDE [Configure a deployment user](../../includes/configure-deployment-user-no-h.md)]
196224

197-
```csharp
198-
// Use SQL Database if in Azure, otherwise, use SQLite
199-
if(Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") == "Production")
200-
services.AddDbContext<MyDatabaseContext>(options =>
201-
options.UseSqlServer(Configuration.GetConnectionString("MyDbConnection")));
202-
else
203-
services.AddDbContext<MyDatabaseContext>(options =>
204-
options.UseSqlite("Data Source=localdatabase.db"));
205-
206-
// Automatically perform database migration
207-
services.BuildServiceProvider().GetService<MyDatabaseContext>().Database.Migrate();
208-
```
225+
### Create an App Service plan
209226

210-
If this code detects that it's running in production (which indicates the Azure environment), then it uses the connection string you configured to connect to the SQL Database.
227+
[!INCLUDE [Create app service plan](../../includes/app-service-web-create-app-service-plan-no-h.md)]
211228

212-
The `Database.Migrate()` call helps you when it's run in Azure, because it automatically creates the databases that your .NET Core app needs, based on its migration configuration.
229+
### Create a web app
213230

214-
> [!IMPORTANT]
215-
> For production apps that need to scale out, follow the best practices in [Applying migrations in production](/aspnet/core/data/ef-rp/migrations#applying-migrations-in-production).
216-
>
231+
[!INCLUDE [Create web app](../../includes/app-service-web-create-web-app-dotnetcore-win-no-h.md)]
217232

218-
Save your changes, then commit it into your Git repository.
233+
### Configure connection string
219234

220-
```bash
221-
git add .
222-
git commit -m "connect to SQLDB in Azure"
235+
To set connection strings for your Azure app, use the [`az webapp config appsettings set`](/cli/azure/webapp/config/appsettings?view=azure-cli-latest#az-webapp-config-appsettings-set) command in the Cloud Shell. In the following command, replace *\<app-name>*, as well as the *\<connection-string>* parameter with the connection string you created earlier.
236+
237+
```azurecli-interactive
238+
az webapp config connection-string set --resource-group myResourceGroup --name <app-name> --settings MyDbConnection="<connection-string>" --connection-string-type SQLAzure
223239
```
224240

241+
In ASP.NET Core, you can use this named connection string (`MyDbConnection`) using the standard pattern, like any connection string specified in *appsettings.json*. In this case, `MyDbConnection` is also defined in your *appsettings.json*. When running in App Service, the connection string defined in App Service takes precedence over the connection string defined in your *appsettings.json*. The code uses the *appsettings.json* value during local development, and the same code uses the App Service value when deployed.
242+
243+
To see how the connection string is referenced in your code, see [Connect to SQL Database in production](#connect-to-sql-database-in-production).
244+
225245
### Push to Azure from Git
226246

227-
[!INCLUDE [app-service-plan-no-h](../../includes/app-service-web-git-push-to-azure-no-h.md)]
247+
[!INCLUDE [push-to-azure-no-h](../../includes/app-service-web-git-push-to-azure-no-h.md)]
228248

229249
<pre>
230-
Counting objects: 98, done.
231-
Delta compression using up to 8 threads.
232-
Compressing objects: 100% (92/92), done.
233-
Writing objects: 100% (98/98), 524.98 KiB | 5.58 MiB/s, done.
234-
Total 98 (delta 8), reused 0 (delta 0)
250+
Enumerating objects: 268, done.
251+
Counting objects: 100% (268/268), done.
252+
Compressing objects: 100% (171/171), done.
253+
Writing objects: 100% (268/268), 1.18 MiB | 1.55 MiB/s, done.
254+
Total 268 (delta 95), reused 251 (delta 87), pack-reused 0
255+
remote: Resolving deltas: 100% (95/95), done.
235256
remote: Updating branch 'master'.
236-
remote: .
237257
remote: Updating submodules.
238-
remote: Preparing deployment for commit id '0c497633b8'.
258+
remote: Preparing deployment for commit id '64821c3558'.
239259
remote: Generating deployment script.
240-
remote: Project file path: ./DotNetCoreSqlDb.csproj
260+
remote: Project file path: .\DotNetCoreSqlDb.csproj
261+
remote: Generating deployment script for ASP.NET MSBuild16 App
241262
remote: Generated deployment script files
242263
remote: Running deployment command...
243-
remote: Handling ASP.NET Core Web Application deployment.
264+
remote: Handling ASP.NET Core Web Application deployment with MSBuild16.
244265
remote: .
245266
remote: .
246267
remote: .
247268
remote: Finished successfully.
248269
remote: Running post deployment command(s)...
249-
remote: Deployment successful.
270+
remote: Triggering recycle (preview mode disabled).
250271
remote: App container will begin restart within 10 seconds.
251-
To https://&lt;app_name&gt;.scm.azurewebsites.net/&lt;app_name&gt;.git
272+
To https://&lt;app-name&gt;.scm.azurewebsites.net/&lt;app-name&gt;.git
252273
* [new branch] master -> master
253274
</pre>
254275

@@ -257,7 +278,7 @@ To https://&lt;app_name&gt;.scm.azurewebsites.net/&lt;app_name&gt;.git
257278
Browse to the deployed app using your web browser.
258279

259280
```bash
260-
http://<app_name>.azurewebsites.net
281+
http://<app-name>.azurewebsites.net
261282
```
262283

263284
Add a few to-do items.
@@ -278,17 +299,12 @@ Open _Models\Todo.cs_ in the code editor. Add the following property to the `ToD
278299
public bool Done { get; set; }
279300
```
280301

281-
### Run Code First Migrations locally
302+
### Rerun database migrations
282303

283-
Run a few commands to make updates to your local database.
304+
Run a few commands to make updates to the production database.
284305

285306
```bash
286307
dotnet ef migrations add AddProperty
287-
```
288-
289-
Update the local database:
290-
291-
```bash
292308
dotnet ef database update
293309
```
294310

@@ -360,7 +376,7 @@ Once the `git push` is complete, navigate to your App Service app and try adding
360376

361377
![Azure app after Code First Migration](./media/app-service-web-tutorial-dotnetcore-sqldb/this-one-is-done.png)
362378

363-
All your existing to-do items are still displayed. When you republish your .NET Core app, existing data in your SQL Database isn't lost. Also, Entity Framework Core Migrations only changes the data schema and leaves your existing data intact.
379+
All your existing to-do items are still displayed. When you republish your ASP.NET Core app, existing data in your SQL Database isn't lost. Also, Entity Framework Core Migrations only changes the data schema and leaves your existing data intact.
364380

365381
## Stream diagnostic logs
366382

@@ -374,7 +390,7 @@ The sample project already follows the guidance at [ASP.NET Core Logging in Azur
374390
To set the ASP.NET Core [log level](https://docs.microsoft.com/aspnet/core/fundamentals/logging#log-level) in App Service to `Information` from the default level `Error`, use the [`az webapp log config`](/cli/azure/webapp/log?view=azure-cli-latest#az-webapp-log-config) command in the Cloud Shell.
375391
376392
```azurecli-interactive
377-
az webapp log config --name <app_name> --resource-group myResourceGroup --application-logging true --level information
393+
az webapp log config --name <app-name> --resource-group myResourceGroup --application-logging true --level information
378394
```
379395

380396
> [!NOTE]
@@ -384,7 +400,7 @@ az webapp log config --name <app_name> --resource-group myResourceGroup --applic
384400
To start log streaming, use the [`az webapp log tail`](/cli/azure/webapp/log?view=azure-cli-latest#az-webapp-log-tail) command in the Cloud Shell.
385401

386402
```azurecli-interactive
387-
az webapp log tail --name <app_name> --resource-group myResourceGroup
403+
az webapp log tail --name <app-name> --resource-group myResourceGroup
388404
```
389405

390406
Once log streaming has started, refresh the Azure app in the browser to get some web traffic. You can now see console logs piped to the terminal. If you don't see console logs immediately, check again in 30 seconds.
@@ -403,7 +419,7 @@ On the **App Services** page, select the name of your Azure app.
403419

404420
![Portal navigation to Azure app](./media/app-service-web-tutorial-dotnetcore-sqldb/access-portal.png)
405421

406-
By default, the portal shows your app's **Overview** page. This page gives you a view of how your app is doing. Here, you can also perform basic management tasks like browse, stop, start, restart, and delete. The left side of the page shows the different configuration pages you can open.
422+
By default, the portal shows your app's **Overview** page. This page gives you a view of how your app is doing. Here, you can also perform basic management tasks like browse, stop, start, restart, and delete. The tabs on the left side of the page show the different configuration pages you can open.
407423

408424
![App Service page in Azure portal](./media/app-service-web-tutorial-dotnetcore-sqldb/web-app-blade.png)
409425

@@ -425,4 +441,4 @@ What you learned:
425441
Advance to the next tutorial to learn how to map a custom DNS name to your app.
426442

427443
> [!div class="nextstepaction"]
428-
> [Map an existing custom DNS name to Azure App Service](app-service-web-tutorial-custom-domain.md)
444+
> [Tutorial: Map custom DNS name to your app](app-service-web-tutorial-custom-domain.md)

0 commit comments

Comments
 (0)