본문 바로가기

WEB/ASP.NET

[ASP.NET 공부] Micro ORM인 Dapper 다루기 - 짱우의 코딩일기 - 티스토리

반응형

  'ASP.NET & Core를 다루는 기술'이라는 책을 통해서 ASP.NET 공부를 하기 시작했다. 아직 많이 읽어보질 못해 평가하기는 좀 그렇지만 예제랑 설명이 적절하게 섞여서 나온 책인 것 같다. 위의 책을 바탕으로 공부한 내용을 글로 쓰려한다.


  지금까지 ADO.NET의 주요 클래스를 사용해서 데이터베이스 관련 코드를 작성하다 보면 반복되는 코드가 발생했었다. 이때 ORM(Object Relational Mapper)이라는 프레임워크를 활용하면 데이터베이스 처리 관련 코드가 많이 줄어들어 생산성을 향상시킬 수 있다. ORM 중에서 'Entity Framework'가 널리 사용된다. 하지만 내용이 많기 때문에 책에서는 'Dapper'를 사용한다.

실습 (Micro ORM인 Dapper를 사용한 DB 코드 간소화하기)

프로젝트 생성 및 Dapper 참조 추가

  • 나 같은 경우에는 디렉토리를 추가해서 실습을 했기 때문에 'DevDapper' 디렉토리를 하나 생성해주었다.
  • 보기 -> 다른 창 -> 패키지 관리자 콘솔을 클릭해 패키지 관리자 콘솔을 실행한다. 그리고 'Install-Package Dapper' 명령어를 입력해서 Dapper를 설치해준다.
  • DevDapper 디렉토리 내에 Models라는 디렉토리를 하나 더 생성하고 'Maxim.cs' 클래스를 추가해준다.

Model(모델) 클래스 및 LocalDB 생성

Maxim.cs

/// <summary>
/// Maxim 클래스 === Maxims 테이블
/// </summary>
public class Maxim
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Content { get; set; }
    public DateTime CreationDate { get; set; }
}

  이번 실습에서 사용할 데이터베이스는 'LocalDB'를 사용한다. 따라서 LocalDB를 생성해준다.

  테이블은 위와 같이 'Maxim' 이라는 이름의 테이블을 생성해주었다. ID는 Primary Key고 Identity를 적용해서 1씩 증가하도록 만들어주었다. CreationDate는 기본값을 GetDate() 함수를 이용해주었다.

  해당 데이터베이스에 연결할 수 있도록 Web.config 코드도 수정해준다.

데이터 입력, 출력, 상세, 수정, 삭제에 대한 기본 코드 작성

  • DevDapper 디렉토리 안에 Repositories 디렉토리를 추가하고 그 안에 'MaximServiceRepository.cs' 클래스 파일을 만들어 준다.
  • 다음과 같이 뼈대를 잡는 코드를 구성한다.

MaximServiceRepository.cs

using ASP_Practice.Day0128.DevDapper.Models;
using Dapper;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Web;

namespace ASP_Practice.Day0128.DevDapper.Repositories
{
    /// <summary>
    /// 명언(Maxim) 서비스에 대한 DB 연동 코드 부분
    /// </summary>
    public class MaximServiceRepository
    {
        // Database Connection 개체 생성
        private IDbConnection db = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);

        // 입력
        public Maxim AddMaxim (Maxim model)
        {
            string sql = @"INSERT INTO Maxim (Name, Content) VALUES (@Name, @Content);
                            SELECT CAST(SCOPE_IDENTITY() AS INT);";
            var id = db.Query<int>(sql, model).Single();
            model.ID = id;
            return model;
        }

        // 출력
        public List<Maxim> GetMaxims ()
        {
            string sql = "SELECT * FROM Maxim ORDER BY ID ASC";
            return db.Query<Maxim>(sql).ToList();
        }

        // 상세
        public Maxim GetMaximByID (int id)
        {
            string sql = "SELECT * FROM Maxim WHERE ID = @ID";
            return db.Query<Maxim>(sql, new { ID = id }).SingleOrDefault();
        }

        // 수정
        public Maxim UpdateMaxim (Maxim model)
        {
            string sql = "UPDATE Maxim SET Name = @Name, Content = @Content WHERE ID = @ID";
            db.Execute(sql, model);
            return model;
        }

        // 삭제
        public void RemoveMaxim (int id)
        {
            string sql = "DELETE Maxim WHERE ID = @ID";
            db.Execute(sql, new { ID = id });
        }
    }
}

ASP.NET 웹 폼에서 CRUD 테스트

  위에서 만든 'MaximServiceRepository.cs'를 테스트해보기 위해 웹 폼 다섯개를 생성한다.

  • FrmMaximWrite.aspx : 입력 테스트
  • FrmMaximList.aspx : 전체 출력 테스트
  • FrmMaximView.aspx : 상세보기 테스트
  • FrmMaximModify.aspx : 수정 테스트
  • FrmMaximDelete.aspx : 삭제 테스트

FrmMaximWrite.aspx

... 생략 ...

<div>
    이름 : <asp:TextBox ID="txtName" runat="server"></asp:TextBox> <br />
    명언 : <asp:TextBox ID="txtContent" runat="server"></asp:TextBox><br />
    <asp:Button ID="btnWrite" runat="server" Text="저장" OnClick="btnWrite_Click" /><br />
    <asp:Label ID="lblDisplay" runat="server"></asp:Label>
    <hr />
    <asp:HyperLink ID="lnkList" runat="server" NavigateUrl="~/Day0128/DevDapper/FrmMaximList.aspx">리스트</asp:HyperLink>
</div>

... 생략 ...

FrmMaximWrite.aspx.cs

... 생략 ...

protected void btnWrite_Click(object sender, EventArgs e)
{
    Maxim maxim = new Maxim();
    maxim.Name = txtName.Text;
    maxim.Content = txtContent.Text;
    MaximServiceRepository repo = new MaximServiceRepository();
    maxim.ID = repo.AddMaxim(maxim).ID;

    lblDisplay.Text = maxim.ID.ToString() + "번 데이터가 입력되었습니다.";
}

  • 해당 TextBox에 입력한 값들을 Maxim 클래스에 담아주고 MaximServiceRepository의 AddMaxim 메서드의 매개변수에 넣어준다.
  • AddMaxim 메서드에서 해당 값들을 insert문으로 테이블에 넣어주고 해당 글의 ID 값을 반환해준다.
  • 다시 웹 페이지에는 insert가 성공하면 받은 id값을 가지고 x번 데이터가 입력되었다는 로그를 뿌려준다.

FrmMaximList.aspx

<div>
    <asp:GridView ID="lstMaxims" runat="server">
        <Columns>
            <asp:HyperLinkField Text="상세보기" DataNavigateUrlFormatString="~/Day0128/DevDapper/FrmMaximView.aspx?ID={0}" DataNavigateUrlFields="ID" />
        </Columns>
    </asp:GridView>
    <hr />
    <asp:HyperLink ID="lnkWrite" runat="server" NavigateUrl="~/Day0128/DevDapper/FrmMaximWrite.aspx">입력</asp:HyperLink>
</div>

FrmMaximList.aspx.cs

protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
        DisplayData();
}

private void DisplayData()
{
    MaximServiceRepository repo = new MaximServiceRepository();

    lstMaxims.DataSource = repo.GetMaxims();
    lstMaxims.DataBind();
}

 

FrmMaximView.aspx

<div>
    번호 : <asp:Label ID="lblID" runat="server"></asp:Label><br />
    이름 : <asp:Label ID="lblName" runat="server"></asp:Label><br />
    명언 : <asp:Label ID="lblContent" runat="server"></asp:Label><br />
    <hr />
    <asp:HyperLink ID="btnModify" runat="server">수정</asp:HyperLink>
    <asp:HyperLink ID="btnDelete" runat="server">삭제</asp:HyperLink>
    <asp:HyperLink ID="lnkList" runat="server" NavigateUrl="~/Day0128/DevDapper/FrmMaximList.aspx">리스트</asp:HyperLink>
</div>

FrmMaximView.aspx.cs

protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
        DisplayData();
}

private void DisplayData()
{
    int id = Convert.ToInt32(Request.QueryString["ID"]);

    MaximServiceRepository repo = new MaximServiceRepository();
    Maxim maxim = repo.GetMaximByID(id);

    lblID.Text = id.ToString();
    lblName.Text = maxim.Name;
    lblContent.Text = maxim.Content;

    btnModify.NavigateUrl = "FrmMaximModify.aspx?ID=" + id;
    btnDelete.NavigateUrl = "FrmMaximDelete.aspx?ID=" + id;
}

 

FrmMaximModify.aspx

<div>
    번호 : <asp:Label ID="lblID" runat="server"></asp:Label><br />
    이름 : <asp:TextBox ID="txtName" runat="server"></asp:TextBox><br />
    명언 : <asp:TextBox ID="txtContent" runat="server"></asp:TextBox><br />
    <asp:Button ID="btnModify" runat="server" Text="수정" OnClick="btnModify_Click" /> <br />
    <asp:Label ID="lblDisplay" runat="server"></asp:Label>
    <hr />
    <asp:HyperLink ID="lnkList" runat="server" NavigateUrl="~/Day0128/DevDapper/FrmMaximList.aspx">리스트</asp:HyperLink>
</div>

FrmMaximModify.aspx.cs

protected void Page_Load(object sender, EventArgs e)
{
    if (!String.IsNullOrEmpty(Request.QueryString["ID"]))
    {
        if (!Page.IsPostBack)
            DisplayData();
    }
    else
    {
        Response.Write("잘못된 요청입니다.");
        Response.End();
    }
}

private void DisplayData()
{
    int id = Convert.ToInt32(Request.QueryString["ID"]);

    MaximServiceRepository repo = new MaximServiceRepository();
    Maxim maxim = repo.GetMaximByID(id);

    lblID.Text = id.ToString();
    txtName.Text = maxim.Name;
    txtContent.Text = maxim.Content;
}

protected void btnModify_Click(object sender, EventArgs e)
{
    Maxim maxim = new Maxim();
    maxim.ID = Convert.ToInt32(Request.QueryString["ID"]);
    maxim.Name = txtName.Text;
    maxim.Content = txtContent.Text;

    MaximServiceRepository repo = new MaximServiceRepository();
    maxim = repo.UpdateMaxim(maxim);

    lblDisplay.Text = maxim.ID.ToString() + "번 데이터가 수정되었습니다.";

    DisplayData();
}

 

FrmMaximDelete.aspx

<div>
    <asp:Label ID="lblID" runat="server"></asp:Label>
    번 글을 삭제하시겠습니까?
    <asp:Button ID-="btnDelete" runat="server" Text="삭제" OnClick="Unnamed_Click" />
    <hr />
    <asp:HyperLink ID="lnkList" runat="server" NavigateUrl="~/Day0128/DevDapper/FrmMaximList.aspx">리스트</asp:HyperLink>
</div>

FrmMaximDelete.aspx.cs

protected void Page_Load(object sender, EventArgs e)
{
    if (!String.IsNullOrEmpty(Request.QueryString["ID"]))
    {
        if (!Page.IsPostBack)
            lblID.Text = Request["ID"];
    }
    else
    {
        Response.Write("잘못된 요청입니다.");
        Response.End();
    }
}

protected void Unnamed_Click(object sender, EventArgs e)
{
    int id = Convert.ToInt32(Request.QueryString["ID"]);

    MaximServiceRepository repo = new MaximServiceRepository();
    repo.RemoveMaxim(id);

    // 리스트 페이지로 이동
    Response.RedirectPermanent("FrmMaximList.aspx");
}

반응형