Упражнение. Подключение приложения ASP.NET к Базе данных SQL Azure
Теперь база данных создана. Теперь вы можете настроить и развернуть веб-приложение, которое академические консультанты могут использовать для обсуждения курсов и планов обучения с учащимися. Приложение использует System.Data.SqlClient
библиотеку для получения и отображения сведений о курсах и модулях, которые учащийся должен пройти для завершения курса.
Чтобы сэкономить время, мы используем предварительно существующее веб-приложение и покажем, как добавить код, который подключает это приложение к базе данных. На следующей схеме показаны основные компоненты этого приложения:
Чтобы настроить веб-приложение, выполните следующие действия.
- создадите класс, содержащий название курса, название модуля и порядок выполнения;
- создадите класс контроллера доступа к данным для получения сведений из базы данных;
- измените код страницы индексов в веб-приложении для создания объекта контроллера доступа к данным и получения данных;
- измените страницу индексов для отображения данных.
Развертывание и запуск существующего веб-приложения
Измените рабочий каталог на папку
education
.cd ~/education
Выполните следующие команды, чтобы выполнить сборку исходного веб-приложения и развернуть его:
WEBAPPNAME=educationapp-$RANDOM az webapp up \ --resource-group <rgn>[Sandbox resource group]</rgn> \ --location centralus \ --sku F1 \ --name $WEBAPPNAME
При развертывании веб-приложения выходные данные отображают App_url с URL-адресом веб-сайта. Откройте этот сайт на новой вкладке.
Вам необходимо, чтобы в веб-приложении выводился список курсов и модулей, из которых состоит определенный курс. В настоящее время приложение не получает и не отображает эти данные. Итак, вам нужно обновить код, чтобы получить данные из базы данных и отобразить их.
Добавление в веб-приложение кода для получения данных
Давайте добавим в приложение код, получающий из базы данных сведения о курсах.
В Cloud Shell перейдите в папку
education/Models
.cd ~/education/Models
Эта папка содержит два файла и
CoursesAndModules.cs
DataAccessController.cs
.Откройте файл с помощью редактора
CoursesAndModules.cs
кода.code CoursesAndModules.cs
Этот файл содержит пустой класс
CoursesAndModules
.namespace CoursesWebApp.Models { public class CoursesAndModules { // TODO: Define the CourseName, ModuleTitle, and Sequence read-only properties // TODO: Create a constructor that initializes the fields behind the properties } }
Замените комментарий
// TODO: Define the CourseName, ModuleTitle, and Sequence read-only properties
следующим кодом.public string CourseName { get; } public string ModuleTitle { get; } public int Sequence { get; }
Этот код определяет набор полей только для чтения, содержащих данные для каждой строки, отображаемой веб-приложением.
Замените комментарий
// TODO: Create a constructor that initializes the fields behind the properties
следующим конструктором:public CoursesAndModules(string courseName, string moduleTitle, int sequence) { this.CourseName = courseName; this.ModuleTitle = moduleTitle; this.Sequence = sequence; }
Этот конструктор заполняет поля отображаемыми данными. В полном виде код файла должен выглядеть так:
namespace CoursesWebApp.Models { public class CoursesAndModules { public string CourseName { get; } public string ModuleTitle { get; } public int Sequence { get; } public CoursesAndModules(string courseName, string moduleTitle, int sequence) { this.CourseName = courseName; this.ModuleTitle = moduleTitle; this.Sequence = sequence; } } }
Сохраните файл, нажав CTRL+S, и закройте редактор кода, нажав CTRL+Q.
Откройте файл с помощью редактора
DataAccessController.cs
кода.code DataAccessController.cs
Файл содержит класс
DataAccessController
. Этот класс содержит логику доступа к данным для подключения к базе данных и получения данных курса и модуля. Он заполняет список объектов даннымиCoursesAndModules
.using Microsoft.Extensions.Options; using System; using System.Collections.Generic; using System.Data; using System.Data.SqlClient; using System.Linq; using System.Threading.Tasks; namespace CoursesWebApp.Models { public class DataAccessController { // TODO: Add your connection string in the following statements private string connectionString = "<Azure SQL Database Connection String>"; // Retrieve all details of courses and their modules public IEnumerable<CoursesAndModules> GetAllCoursesAndModules() { List<CoursesAndModules> courseList = new List<CoursesAndModules>(); // TODO: Connect to the database //using () { // TODO: Specify the Transact-SQL query to run // TODO: Execute the query // TODO: Read the data a row at a time // TODO: Close the database connection } return courseList; } } }
Не закрывая редактор кода, перейдите на портал Azure.
В меню портала Microsoft Azure выберите Базы данных SQL, а затем — свою базу данных. Появится База данных SQL для coursedatabaseNNN.
На панели меню слева выберите Параметры, а затем — Строки подключения. Скопируйте строку подключения ADO.NET в буфер обмена.
Вернитесь в редактор кода. Замените значение переменной connectionString содержимым буфера обмена. В строке подключения найдите текст
User ID
со значениемazuresql
. Замените текст{your_password}
паролем для этой учетной записи.private string connectionString = "Server=tcp:courseservernnn.database.windows.net,1433;Initial Catalog=coursedatabasennn;Persist Security Info=False;User ID=azuresql;Password=<password>;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;";
После комментария
//TODO: Connect to the database
замените закомментированный операторusing
следующим кодом:using (SqlConnection con = new SqlConnection(connectionString))
Этот код создает объект
SqlConnection
, который устанавливает подключение к базе данных с использованием указанной строки подключения.Замените комментарий
// TODO: Specify the Transact-SQL query to run
следующими инструкциями:SqlCommand cmd = new SqlCommand( @"SELECT c.CourseName, m.ModuleTitle, s.ModuleSequence FROM dbo.Courses c JOIN dbo.StudyPlans s ON c.CourseID = s.CourseID JOIN dbo.Modules m ON m.ModuleCode = s.ModuleCode ORDER BY c.CourseName, s.ModuleSequence", con); cmd.CommandType = CommandType.Text;
Объект
SqlCommand
содержит инструкцию Transact-SQL (T-SQL), которая извлекает данные для всех курсов и модулей. Он объединяет их с помощью сведенийdbo.StudyPlan
в таблице.Замените комментарий
// TODO: Execute the query
следующим кодом.con.Open(); SqlDataReader rdr = cmd.ExecuteReader();
Эти инструкции открывают подключение к базе данных и запускают инструкцию T-SQL. С помощью объекта
SqlDataReader
можно получать результаты по одной строке за раз.Замените комментарий
// TODO: Read the data a row at a time
следующим блоком кода:while (rdr.Read()) { string courseName = rdr["CourseName"].ToString(); string moduleTitle = rdr["ModuleTitle"].ToString(); int moduleSequence = Convert.ToInt32(rdr["ModuleSequence"]); CoursesAndModules course = new CoursesAndModules(courseName, moduleTitle, moduleSequence); courseList.Add(course); }
Этот блок перебирает строки, возвращаемые в объекте
SqlDataReader
. Он извлекает данные из полей каждой строки и заполняет ими новый объектCoursesAndModules
. Затем этот объект добавляется в список.Замените комментарий
// TODO: Close the database connection
следующим оператором:con.Close();
Этот оператор закрывает подключение к базе данных и высвобождает выделенные ресурсы.
В полном виде класс должен содержать следующий код со строкой подключения к вашей базе данных:
using Microsoft.Extensions.Options; using System; using System.Collections.Generic; using System.Data; using System.Data.SqlClient; using System.Linq; using System.Threading.Tasks; namespace CoursesWebApp.Models { public class DataAccessController { // Add your connection string in the following statements private string connectionString = "Server=tcp:courseserver101.database.windows.net,1433;Initial Catalog=coursedatabase101;Persist Security Info=False;User ID=azuresql;Password=<password>;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"; // Retrieve all details of courses and their modules public IEnumerable<CoursesAndModules> GetAllCoursesAndModules() { List<CoursesAndModules> courseList = new List<CoursesAndModules>(); // Connect to the database using (SqlConnection con = new SqlConnection(connectionString)) { // Specify the Transact-SQL query to run SqlCommand cmd = new SqlCommand( @"SELECT c.CourseName, m.ModuleTitle, s.ModuleSequence FROM dbo.Courses c JOIN dbo.StudyPlans s ON c.CourseID = s.CourseID JOIN dbo.Modules m ON m.ModuleCode = s.ModuleCode ORDER BY c.CourseName, s.ModuleSequence", con); cmd.CommandType = CommandType.Text; // Execute the query con.Open(); SqlDataReader rdr = cmd.ExecuteReader(); // Read the data a row at a time while (rdr.Read()) { string courseName = rdr["CourseName"].ToString(); string moduleTitle = rdr["ModuleTitle"].ToString(); int moduleSequence = Convert.ToInt32(rdr["ModuleSequence"]); CoursesAndModules course = new CoursesAndModules(courseName, moduleTitle, moduleSequence); courseList.Add(course); } // Close the database connection con.Close(); } return courseList; } } }
Сохраните файл и закройте редактор Code.
Добавление в веб-приложение кода для отображения данных
Теперь приложение может извлекать сведения о курсах. Измените его так, чтобы в нем выводились сведения о курсах.
В Cloud Shell перейдите в папку
education/Pages
.cd ~/education/Pages
Эта папка содержит страницы CSHTML и файлы кода, которые веб-приложение использует для отображения данных.
Откройте файл с помощью редактора
Index.cshtml.cs
кода.code Index.cshtml.cs
Этот файл содержит код, который выполняется при отображении страницы индексов. В нем определен класс
CoursesAndModulesModel
. Страница индекса использует эту модель для отображения сведений о курсах и модулях. В файл нужно добавить код, использующий объектDataAccessController
для получения данных.using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using CoursesWebApp.Models; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; namespace CoursesWebApp.Pages { public class CoursesAndModulesModel : PageModel { // TODO: Create a DataAccessController object // TODO: Create a collection for holding CoursesAndModules object public void OnGet() { // TODO: Retrieve the data using the DataAccessController object and populate the CoursesAndModules object } } }
В
Index.cshtml.cs
окне замените комментарий// TODO: Create a DataAccessController object
следующим кодом, чтобы создать новыйDataAccessController
объект.DataAccessController dac = new DataAccessController();
Замените комментарий
// TODO: Create a collection for holding CoursesAndModules object
следующим кодом.public List<CoursesAndModules> CoursesAndModules;
В методе
OnGet
замените комментарий// TODO: Retrieve the data using the DataAccessController object and populate the CoursesAndModules object
приведенным ниже кодом. В нем объектDataAccessController
используется для заполнения списка данными из базы данных.CoursesAndModules = dac.GetAllCoursesAndModules().ToList();
Код готового файла должен выглядеть так:
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using CoursesWebApp.Models; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; namespace CoursesWebApp.Pages { public class CoursesAndModulesModel : PageModel { // Create a DataAccessController object DataAccessController dac = new DataAccessController(); // Create a collection for holding CoursesAndModules object public List<CoursesAndModules> CoursesAndModules; public void OnGet() { // Retrieve the data using the DataAccessController object and populate the CoursesAndModules object CoursesAndModules = dac.GetAllCoursesAndModules().ToList(); } } }
Сохраните файл и закройте редактор кода.
Откройте файл
Index.cshtml
с помощью редактора кода.code Index.cshtml
Этот файл содержит логику отображения данных для страницы индексов. В качестве источника данных указан объект
CoursesAndModulesModel
. Добавленный вами код создает и заполняет эту модель.Данные из модели отображаются на странице в формате HTML. В настоящее время на странице выводятся только заголовки таблиц. Их содержимое (
<tbody>
) отсутствует.<h2>Courses and Modules</h2> <div> <table class="table"> <thead> <tr> <th> Course Name </th> <th> Modules </th> <th> Sequence </th> </tr> </thead> <tbody> <!-- TODO: Display the data from the CoursesAndModules collection --> </tbody> </table> </div>
Замените комментарий
<!-- TODO: Display the data from the CoursesAndModules collection --\>
следующей разметкой:@foreach(var courseAndModule in Model.CoursesAndModules) { <tr> <td> @Html.DisplayFor(courseName => courseAndModule.CourseName) </td> <td> @Html.DisplayFor(moduleTitle => courseAndModule.ModuleTitle) </td> <td> @Html.DisplayFor(sequence => courseAndModule.Sequence) </td> </tr> }
Этот код перебирает строки модели и выводит данные в каждом поле.
Завершенный
Index.cshtml
файл должен содержать следующий код.@page @model CoursesAndModulesModel @{ ViewData["Title"] = "Home page"; } <h2>Courses and Modules</h2> <div> <table class="table"> <thead> <tr> <th> Course Name </th> <th> Modules </th> <th> Sequence </th> </tr> </thead> <tbody> @foreach(var courseAndModule in Model.CoursesAndModules) { <tr> <td> @Html.DisplayFor(courseName => courseAndModule.CourseName) </td> <td> @Html.DisplayFor(moduleTitle => courseAndModule.ModuleTitle) </td> <td> @Html.DisplayFor(sequence => courseAndModule.Sequence) </td> </tr> } </tbody> </table> </div>
Сохраните файл и закройте редактор кода.
Развертывание и тестирование измененного веб-приложения
Полностью настроив приложение для получения и отображения сведений о курсах, вы можете развернуть его обновленную версию.
В Cloud Shell вернитесь в папку
education
.cd ~/education
Выполните следующие команды, чтобы выполнить сборку обновленного веб-приложения и развернуть его.
az webapp up \ --resource-group <rgn>[Sandbox resource group]</rgn> \ --name $WEBAPPNAME
После развертывания нового веб-приложения выберите ссылку приложения. Теперь в нем должен отображаться список курсов и модулей на основе сведений из базы данных.