연습 - Azure SQL Database에 ASP.NET 애플리케이션 연결

완료됨

데이터베이스가 만들어졌습니다. 이제 지도 교수가 학생들과 함께 학습 과정과 계획을 논의하는 데 사용할 수 있는 웹 애플리케이션을 구성하고 배포할 수 있습니다. 이 앱은 System.Data.SqlClient 라이브러리를 사용하여 과정 및 학생들이 과정을 완료하기 위해 통과해야 하는 모듈의 세부 정보를 검색하고 표시합니다.

시간을 절약하기 위해 기존 웹 애플리케이션을 사용하고 이 앱을 데이터베이스에 연결하는 코드를 추가하는 방법을 보여 줍니다. 다음 다이어그램은 이 앱의 기본 구성 요소를 보여 줍니다.

High-level view of the application structure.

웹 애플리케이션을 구성하려면 다음을 수행합니다.

  • 과정 이름, 모듈 제목 및 데이터베이스의 각 모듈 순서를 포함하는 ‘클래스’를 만듭니다.
  • 데이터베이스에서 정보를 검색하는 ‘데이터 액세스 컨트롤러 클래스’를 만듭니다.
  • 웹앱의 인덱스 페이지 뒤에 있는 코드를 편집하여 ‘데이터 액세스 컨트롤러 개체’를 만들고 데이터를 가져옵니다.
  • 인덱스 페이지를 편집하여 데이터를 표시합니다.

기존 웹앱 배포 및 실행

  1. 작업 디렉터리를 education 폴더로 변경합니다.

    cd ~/education
    
  2. 다음 명령을 실행하여 초기 웹 애플리케이션을 빌드하고 배포합니다.

    WEBAPPNAME=educationapp-$RANDOM
    az webapp up \
        --resource-group <rgn>[Sandbox resource group]</rgn> \
        --location centralus \
        --sku F1 \
        --name $WEBAPPNAME
    
  3. 웹 애플리케이션이 배포되면 웹 사이트의 URL이 있는 App_url이 출력에 표시됩니다. 새 탭에서 이 사이트를 엽니다.

    The education web app running. Currently, no data is displayed.

    웹앱에서 과정 목록과 각 과정을 구성하는 모듈을 표시하려고 합니다. 지금은 앱이 이 데이터를 검색하거나 표시하지 않습니다. 따라서 데이터베이스에서 데이터를 가져와 표시하도록 코드를 업데이트해야 합니다.

웹앱에 데이터 검색 코드 추가

이제 데이터베이스에서 과정 데이터를 검색하는 코드를 애플리케이션에 추가하겠습니다.

  1. Cloud Shell에서 education/Models 폴더로 이동합니다.

    cd ~/education/Models
    

    이 폴더에는 다음 두 개의 파일이 포함되어 있습니다. CoursesAndModules.csDataAccessController.cs

  2. 코드 편집기를 사용하여 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
        }
    }
    
  3. // TODO: Define the CourseName, ModuleTitle, and Sequence read-only properties 주석을 다음 코드로 바꿉니다.

    public string CourseName { get; }
    public string ModuleTitle { get; }
    public int Sequence { get; }
    

    이 코드는 웹 애플리케이션이 표시하는 각 행의 데이터를 포함할 읽기 전용 필드 집합을 정의합니다.

  4. // 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;
            }
        }
    }
    
  5. Ctrl+S를 눌러 파일을 저장하고 Ctrl+Q를 눌러 코드 편집기를 닫습니다.

  6. 코드 편집기를 사용하여 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;
            }
        }
    }
    
  7. 코드 편집기를 열어두고 Azure Portal로 전환합니다.

  8. Azure Portal 메뉴에서 SQL 데이터베이스를 선택한 후 데이터베이스를 선택합니다. coursedatabaseNNN에 대한 SQL 데이터베이스가 나타납니다.

  9. 왼쪽 메뉴 창의 설정에서 연결 문자열을 선택합니다. ADO.NET 연결 문자열을 클립보드에 복사합니다.

    The connection string pane in the Azure portal.

  10. 코드 편집기로 돌아갑니다. 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;";
    
  11. //TODO: Connect to the database 주석 뒤에서 주석으로 처리된 using 문을 다음 코드로 바꿉니다.

    using (SqlConnection con = new SqlConnection(connectionString))
    

    이 코드는 연결 문자열을 사용하여 데이터베이스에 연결하는 새 SqlConnection 개체를 만듭니다.

  12. // 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 개체는 모든 과정과 모듈의 데이터를 검색하는 T-SQL(Transact-SQL) 문을 포함합니다. 이 개체는 dbo.StudyPlan 테이블의 정보를 사용하여 데이터를 조인합니다.

  13. // TODO: Execute the query 주석을 다음 코드로 바꿉니다.

    con.Open();
    SqlDataReader rdr = cmd.ExecuteReader();
    

    이 문은 데이터베이스에 대한 연결을 열고 T-SQL 문을 실행합니다. SqlDataReader 개체를 사용하여 결과를 한 번에 한 행씩 가져올 수 있습니다.

  14. // 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 개체를 채우는 데 사용합니다. 그런 다음, 이 개체가 목록에 추가됩니다.

  15. // 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;
            }
        }
    }
    
  16. 파일을 저장하고 코드 편집기를 닫습니다.

웹앱에 데이터 표시 코드 추가

이제 애플리케이션이 과정 데이터를 검색할 수 있습니다. 이 데이터를 사용자에게 표시하도록 앱을 업데이트하겠습니다.

  1. Cloud Shell에서 education/Pages 폴더로 이동합니다.

    cd ~/education/Pages
    

    이 폴더에는 웹앱에서 정보를 표시하는 데 사용하는 코드 파일과 .cshtml 페이지가 있습니다.

  2. 코드 편집기를 사용하여 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
            }
        }
    }
    
  3. Index.cshtml.cs// TODO: Create a DataAccessController object 주석을 새 DataAccessController 개체를 만드는 다음 코드로 바꿉니다.

    DataAccessController dac = new DataAccessController();
    
  4. // TODO: Create a collection for holding CoursesAndModules object 주석을 다음 코드로 바꿉니다.

    public List<CoursesAndModules> CoursesAndModules;
    
  5. 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();
            }
        }
    }
    
  6. 파일을 저장하고 코드 편집기를 닫습니다.

  7. 코드 편집기를 사용하여 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>
    
  8. <!-- 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>
    
  9. 파일을 저장하고 코드 편집기를 닫습니다.

업데이트된 웹앱 배포 및 테스트

과정 데이터를 검색하여 사용자에게 표시하도록 애플리케이션을 완전히 구성했으면, 업데이트된 버전을 배포할 수 있습니다.

  1. Cloud Shell에서 education 폴더로 돌아갑니다.

    cd ~/education
    
  2. 다음 명령을 실행하여 업데이트된 웹앱을 빌드하고 배포합니다.

    az webapp up \
        --resource-group <rgn>[Sandbox resource group]</rgn> \
        --name $WEBAPPNAME
    
  3. 새 웹앱을 배포한 후에 앱의 링크를 선택합니다. 이제 데이터베이스에 저장된 데이터와 함께 과정 및 모듈 목록이 표시됩니다.

    Screenshot of the education web app running, showing the data.