MixedCode

4일차
4.1 모델 & 데이터 모델링 & 데이터 베이스

4.2 Microsoft SQL Server 기초
4.3 Entity Framework(EF) ORM 사용법
4.4 EF 기반 ASP.NET MVC DB Programming

EF를 이용한 DB프로그래밍을 시작하겠습니다.

1.EF 모델 기반 DB 프로그래밍1(기초) 

 EF를 이용한 모델기반 DB프로그래밍을 회원가입 시나리오대로 순차적으로 진행해보도록 하겠습니다.

STEP1.회원가입하기


1)회원가입처리를 위한 MemberController를 신규로 생성합니다.
-Controllers폴더에 오른쪽마우스 클릭 추가>컨트롤러 선택 후
-MVC5 컨트롤러-비어있음을 선택 추가합니다.
-컨트롤러명을 입력하고 확인합니다. EX) MemberController


2)  EDMX 파일내에 존재하는 관련객체를 참조하고 DB처리 객체를 생성합니다.
-컨트롤러 상단에 기존에 생성한 EF관련 네임스페이스를 참조합니다.
using EddyHomePage.Models;

-
객체모델을 통한 DB 데이터 처리를 위한 관련 DB객체를 상단에 정의합니다.
 EddyHomePageEntities db = new EddyHomePageEntities();

3)사용자가 URL(/Member/Entry)을 통해 최초 호출하는 HTTP GET방식의 액션메소드를 추가합니다.
-액션메소드내에 회원정보를 관리하는 EF모델객체인 Member 모델객체를 생성하고 뷰에 모델을 전달합니다.
-모델을 통한 DB프로그래밍을 하기위해서는 모델을 생성하고 뷰에 모델을 전달해야합니다.

  [HttpGet]
  public ActionResult Entry()
  {
       Member member = new Member();
       return View(member);
  }


4)GET 액션메소드의 뷰를 생성합니다.
-액션메소드에 오른쪽 마우스 클릭 뷰추가를 클릭합니다.
-관련 레이아웃 페이지를 선택하고 추가를 클릭합니다.
-해당 뷰를 오픈하고 컨트롤로에서 전달한 모델 사용을 위해 뷰최상단에 모델 네임스페이스를 참조합니다.
@using EddyHomePage.Models;

-액션메소드에서 전달된 모델의 유형을 @model이란 별칭으로 정의합니다.
@model  EddyHomePage.Models.Member

-뷰의 반응형웹 템플릿을 복사하여 붙여넣은 후 form태그 아래와 같이 구성합니다.
         
<form method="post" action="@Url.Action("Entry", "Member")" class="wpcf7-form">

    <div class="field">
        @Html.TextBoxFor(m => m.MemberID, new { placeholder = "아이디를 입력하세요." })
    </div>
    <div class="field">
        @Html.TextBoxFor(m => m.MemberName, new { placeholder = "이름을 입력하세요." })
    </div>
    <div class="field">
        @Html.TextBoxFor(m => m.MemberPWD, new { placeholder = "암호를 입력하세요." })
    </div>
    <div class="field">
        @Html.TextBoxFor(m => m.Email, new { placeholder = "메일을 입력하세요." })
    </div>
    <div class="field">
        @Html.TextBoxFor(m => m.Telephone, new { placeholder = "전화번호를 입력하세요." })
    </div>
    <div class="dividewhite2"></div>
    <div class="field text-center">
        <button type="submit" class="btn btn-lg btn-lgr-str">Send Message</button>
    </div>
</form>

-form 태그내의 입력요소에 바인딩된 모델 정보는 사용자가 submit버튼을 클릭하면 http post방식으로 MemberController의 Entry 액션메소드로 전송됩니다.
-Html클래스에는 각종 입력요소를 자동으로 생성해주는 다양한 메소드가 존재하며 TextBoxFor메소드는 모델이 속성명을
기반으로 텍스트박스 HTML태그를 자동 렌더링해주는 메소드입니다.
-뷰내의 코드들은 뷰엔진에 의해 HTML로 해석되어 그결과를 HTML로 렌더링하여 웹서버를 통해 브라우저에 전달합니다.


5)사용자가 회원가입화면에 관련정보를 입력합니다.
사용자는 전달받은 입력화면의 입력요소에 데이터를 입력하고 Submit버튼을 클릭하고 FORM태그에 지정된 URL로 데이터를 POST방식으로 전송합니다.


6)POST방식으로 호출된 컨트롤러의 POST 액션메소드는 뷰에 바인딩된 모델정보를 매개변수로 전달받습니다.
-POST방식으로 호출된 Entry액션메소드는 Member모델을 매개변수로 전달받습니다.
-회원가입일자정보를 시스템의 오늘날자로 갱신합니다.
-컨트롤로 상단에 정의해둔 db 객체를 통해 사용자로부터 전달받은 member값을 추가하고 DB에 반영합니다.
-ViewBag Result속성을 정의하고 값을 지정하여 저장결과메시지를 뷰에 전달합니다.
-최종 DB에 반영된 member객체를 다시 뷰에 전달합니다.
      
        [HttpPost]
        public ActionResult Entry(Member member)
        {
            member.RegistDate = DateTime.Now;

            try
            {
                db.Member.Add(member);
                db.SaveChanges();

                ViewBag.Result = "OK";

            }catch(Exception ex)
            {
                ViewBag.Result = "FAIL";
            }
                //return RedirectToAction("List", "Member");

            return View(member);
        }

7) 유효성 검사 및 등록결과 메시지 표시하기
- 뷰페이지에서 Submit버튼을 사용자가 클릭할때 유효성검사를 처리하는 기능을 추가합니다.
- submit버튼 onclick 이벤트에 하단의 자바스크립트 함수를 지정합니다.
- 페이지 제일 하단에 스크립트 섹션을 정의하고 자바스크립트를 코딩합니다.
- 페이지가 로딩될때 ViewBag Result속성값이OK이면 관련 메시지를 출력합니다.
- 컨텐츠 뷰에서 section을 선언해 스크립트 블럭을 선언해 스크립트를 정의해 사용한경우는 반드시 해당 section명이
레이아웃 페이지에서 노출될수있도록  레이아웃페이지 최하단에 @RenderSection("섹션명", 필수노출여부)을 예시와 같이 정의해줘야한다.

ex) @RenderSection("Scripts", required: false)

 <button type="submit" onclick="return fnSaveCheck();"  class="btn btn-lg btn-lgr-str">Send Message</button>

@section Scripts {

    <script>
        $(document).ready(function () {
            var result =
'@ViewBag.Result';
            if (result == 'OK') {
                alert("정상적으로 저장되었습니다.");
            }

            if (result == 'FAIL') {
                alert("저장작업을 실패하였습니다.");
            }
        });

        function fnSaveCheck() {

            if ($("#MemberID").val() == "") {
                alert("아이디를 입력해주십시오.")
                $("#MemberID").focus();
                return false;
            }

            if ($("#MemberName").val() == "") {
                alert("성명을 입력해주십시오.")
                $("#MemberName").focus();
                return false;
            }
            if ($("#MemberPWD").val() == "") {
                alert("암호를 입력해주십시오.")
                $("#MemberPWD").focus();
                return false;
            }

            return true;
        }

    </script>


8)회원가입화면 확인하기
지금까지 Submit버튼을 클릭하면 입력 여부에 대한 유효성 검사를 확인 후 정상적으로 저장이 완료되며 결과메시지가 나타납니다.
가입 후 특정 화면으로 바로 이동하고자 하시면  return View(member); 대신에 return RedirectToAction("Index", "Home"); 으로 코딩하여
HomeController 의 Index란 액션메소드로 이동하게 합니다.


9)회원 아이디 중복체크하기

회원 가입시 중복아이디가 존재하는지 여부를 AJAX 와 OPEN API 기술을 이용해 구현해보도록 하겠습니다.
-먼저 회원아이디 텍스트 박스 옆에 중복검사 버튼을 추가하고 반응형으로 로우 와 컬럼을 설정합니다.
<div class="field">
    <div class="row">
       <div class="col-md-6">@Html.TextBoxFor(m => m.MemberID, new { placeholder = "아이디를 입력하세요." })</div>
       <div class="col-md-2"><button type="button" onclick="return fnDoubleCheck();" class="btn btn-lg btn-lgr-str">중복검사</button></div>
        

    </div>
</div>

-자바스크립트 함수 와 AJAX관련 코딩을 실시합니다.
        //아이디 중복검사
        function fnDoubleCheck() {

            if ($("#MemberID").val() == "") {
                alert("아이디를 입력해주십시오.")
                $("#MemberID").focus();
                return false;
            }

            $.ajax({
                type: "GET",
                contentType: "application/json; charset=utf-8",
                url: '/Member/IDCheck?memberid=' + $("#MemberID").val(),
                data: "{}",
                dataType: "json"
            })
          .done(function (response) {
              //debugger;
              if (response == "OK") {
                  alert("사용가능 아이디입니다.");
                  $("#btnSave").removeAttr("disabled");
              } else {
                  alert("중복 아이디가 존재합니다.");
                  $('#MemberID').val('');
                  $('#MemberID').focus();
                  $("#btnSave").attr("disabled", true);
              }
          })
          .fail(function (data) {
              if (data.responseText !== '') {
                  alert(data.responseText);
              } else {
                  alert("에러가 발생했습니다");
              }
          });
        }


-MemberController에  OPEN API 액션메소드를 추가합니다.
     public JsonResult IDCheck(string memberid)
        {
            string result = string.Empty;
            Member member = db.Member.Find(memberid);
            if (member == null)
            {
                result = "OK";
            }else
            {
                result = "FAIL";
            }
            return Json(result, JsonRequestBehavior.AllowGet);
        }

TIP) AJAX?
-비동기식 자바스크립트 XML(Asynchronous Javascript And XML=에이잭스)의 약자로 클라이언트인 브라우저에서 지원해주는 기술로
일반적인 웹페이지 렌더링 방식인  동기식 웹페이지 호출방식은 웹서버의 웹페이지를 호출하여 HTML결과물을 받아 브라우저 화면을 다시 그려주기 때문에 화면이 껌벅거리는 현상이 존재합니다. AJAX(에이잭스) 기술을 이용하면 서버측에서 데이터와 HTML이 섞여진 결과물을 받는것이
아닌 순수 데이터만을 XML 또는 JSON 데이터  형식으로 받아 웹페이지를 다시 로딩하지 않고 브라우저 기반에서 기 렌더링 HTML 요소의 데이터만을 변경하는 기술입니다.

TIP) OPEN API?
-OPEN API는 웹서버측 기술로 클라이언트에서 AJAX방식으로 데이터 호출 요청이 오면 DATABASE에서 데이터를 조회하여 그결과를 JSON 이나 XML 데이터 형식으로 응답하는 기술로 순수 데이터만을 표준형식(XML,JSON)으로 제공하는 서버측 기술입니다.
-JSON은 키값 형태로 정의된 문자열형식으로 데이터를 정의하여 전달하는 데이터 전달 포맷을 말합니다.



STEP2.회원목록 조회하기
이번에는 가입한 회원정보를 전체 조회하여  목록화면을 구성하고 페이징처리를 해보도록 하겠습니다.

1)MemberController에 List 액션메소드를 추가하고 관련 뷰를 추가합니다.
-Views\Member\List 뷰를 오픈하고 정적인 HTML 컨텐츠를 구성합니다.
-회원목록 템플릿은 템플릿내에 블로그 관련 목록기능을 참조하여 아래와 같이 화면을 구성하였습니다.

<!-- Container -->
<div class="content-wrap">
    <div id="blogpost" class="inner-content">
        <section class="inner-section">
            <div class="container-fluid nopadding">
                <div class="wow fadeInDown" data-wow-delay="0.6s" data-wow-offset="10">
                    <div id="post-comment">
                        <h4 class="font-accident-one-light uppercase">회원 목록</h4>
                    </div>
                    <div class="dividewhite2"></div>

                    <div class="row">
                        <table style="width:100%;">
                            <thead>
                                <tr>
                                    <th width="10%">순번</th>
                                    <th width="10%">고객아이디</th>
                                    <th width="20%">고객명</th>
                                    <th width="20%">전화번호</th>
                                    <th width="20%">메일주소</th>
                                    <th width="20%">가입일시</th>
                                </tr>
                            </thead>
                            <tbody>
                                <tr>
                                    <td>1</td>
                                    <td>EDDY</td>
                                    <td>강창훈</td>
                                    <td>010-2760-5246</td>
                                    <td>test@test.co.kr</td>
                                    <td>2016.09.30</td>
                                </tr>
                            </tbody>
                            <tfoot>
                                <tr>
                                    <td colspan="6" style="text-align:center;">
                                        페이저 영역
                                    </td>
                                </tr>
                            </tfoot>
                        </table>
                    </div>
                </div>

            </div>
            <div class="dividewhite8"></div>
        </section>
    </div>
</div>


2) 회원 목록 액션메소드인 List 메소드에서는 전체 회원목록 데이터를 조회하고  회원목록데이터를 뷰에 전달합니다.
-아래 예시는 회원전체 목록을 조회한 예시와 회원목록에서 아이디와 이름으로 필터링하고 최신가입일자로 정렬하여 목록을 LINQ로 조회한 예시를 주석으로 처리하여 제공하였습니다.

  [HttpGet]
  public ActionResult List()
  {
            List<Member> list = db.Member.OrderByDescending(o => o.RegistDate).ToList();
            //var list = db.Member.Where(c => c.MemberID == "EDDY" && c.MemberName == "강창훈").OrderByDescending(o => o.RegistDate).ToList();
            return View(list);
   }


3)회원목록 뷰에 전달된 회원목록데이터를 테이블 태그로 표시합니다.
-액션메소드에서 전달된 회원목록 데이터를 반복문을 통해 <TR>태그 및 <TD>태그내에 정보를 표시하여 출력합니다.
-회원아이디 항목은 링크태그를 추가하여 클릭시 정보수정 화면으로 이동하게 처리하였습니다.
@using EddyHomePage.Models;
@model  List<EddyHomePage.Models.Member>

<table style="width:100%;">
    <thead>
        <tr>
            <th width="10%">순번</th>
            <th width="10%">고객아이디</th>
            <th width="20%">고객명</th>
            <th width="20%">전화번호</th>
            <th width="20%">메일주소</th>
            <th width="20%">가입일시</th>
        </tr>
    </thead>
    <tbody>
        @{
            int i = 0;
            int idx = 0;
        }

        @foreach (var item in Model)
        {
            idx = Model.Count - i;
            <tr>
                <td>@idx.ToString()</td>
                <td><a href="
/Member/Edit?memberid=@item.MemberID">@item.MemberID</a></td>
                <td>@item.MemberName</td>
                <td>@item.Telephone</td>
                <td>@item.Email</td>
                <td>@Convert.ToDateTime(item.RegistDate).ToString("yyyy.MM.dd")</td>
            </tr>
            i++;
        }
    </tbody>
    <tfoot>
        <tr>
            <td colspan="6" style="text-align:center;">
                페이저 영역
            </td>
        </tr>
    </tfoot>
</table>


4)페이징처리를 위해 Footable JQUERY 플러그인을 추가합니다.
-footable플러그인은 table태그를 이용 페이징,정렬처리,디바이스별 컬럼 보이기 숨기기 기능등을 제공합니다.
http://mixedcode.com/upload/footable.zip
-다운로드후 압축파일을 풉니다.
-footable 폴더를 복사하여 Visual Studio 솔루션 탐색기에 assets\vendor폴더에 붙여넣기합니다.
-붙여넣기 완료 후 트리를 확장하여 하위에 존재하는 폴더파일들을 프로젝트에 포함시킵니다.
-솔루션 탐색기 App_Start폴더내에 BundleConfig.cs파일을 열고 아래와 같이 footable.core.css 와 footable.all.min.js 파일을 추가합니다.



-뷰페이지에서 footable관련 table태그와 javascript  코딩을 추가합니다.

<table class="footable table table-stripped toggle-arrow-tiny" data-page-size="10">
    <thead>
        <tr>
            <th data-toggle="true" data-sort-ignore="true" width="10%">순번</th>
            <th data-sort-ignore="true"  width="10%">고객아이디</th>
            <th width="20%">고객명</th>
            <th data-hide="phone" width="20%">전화번호</th>
            <th data-hide="phone,tablet" width="20%">메일주소</th>
            <th data-hide="phone" class="text-center" width="20%">가입일시</th>
        </tr>
    </thead>
    <tbody>
        @{
            int i = 0;
            int idx = 0;
        }

        @foreach (var item in Model)
        {
            idx = Model.Count - i;
            <tr>
                <td>@idx.ToString()</td>
                <td><a href="
/Member/Edit?memberid=@item.MemberID">@item.MemberID</a></td>
                <td>@item.MemberName</td>
                <td>@item.Telephone</td>
                <td>@item.Email</td>
                <td>@Convert.ToDateTime(item.RegistDate).ToString("yyyy.MM.dd")</td>
            </tr>
            i++;
        }
    </tbody>
    <tfoot>
        <tr>
            <td colspan="6">
               <ul class="pagination pull-right"></ul>
            </td>
        </tr>
    </tfoot>
</table>




@section Scripts {

    <script>
        $(document).ready(function () {
            $('.footable').footable();
        });

    </script>

}

-다음은 footable 플러그인의 주요 설정 및 기능입니다.
<table class="footable table table-stripped toggle-arrow-tiny" data-page-size="10"> : 페이징 건수지정 및 footable table 지정
<th data-toggle="true"> : 디바이스별 해상도에 따라 숨김컬럼데이터를 보이게 할 컬럼설정
<th data-sort-ignore="true"> : 컬럼 헤더를 통해 내림차순/올림차순으로 정렬처리기능 사용여부
<th data-hide="phone,tablet"> : td컬럼 값을 디바이스 해상도별로 선택 숨기기 기능
<ul class="pagination pull-right"></ul> : 페이저 위치 및 정렬처리




STEP3.회원정보 수정.삭제하기

회원목록 뷰에서 회원아이디를 클릭하면 회원정보를 수정하고 삭제하는 기능을 구현하겠습니다.

1)Member Controller에 Get타입의 Edit 액션메소드를 추가합니다.
-첫번째 액션메소드는 GET방식으로 목록에서 회원아이디를 클릭하면 아이디가 List목록에서 Edit수정화면으로 GET방식으로 전달됩니다.
-전달된 회원아이디로 DB에서 회원정보를 조회하여 Edit뷰에 전달합니다.

[HttpGet]
public ActionResult Edit(string memberid)
{
      Member member = db.Member.Where(c => c.MemberID == memberid).FirstOrDefault();
      return View(member);
 }


2)Edit뷰의 컨텐츠를 생성합니다.
-Edit뷰 컨텐츠는 회원가입 Entry뷰를 복사하여 사용합니다.
-수정할 부분은 form태그내 액션 url을 Edit 액션메소드로 변경합니다.
-가입버튼을 수정으로 변경하고 삭제버튼을 추가합니다.
-삭제관련 자바스크립트 함수를 추가합니다.

<form method="post" action="@Url.Action("Edit", "Member")" class="wpcf7-form">

    <div class="field">
        <div class="row">
            <div class="col-md-6">@Html.TextBoxFor(m => m.MemberID, new { placeholder = "아이디를 입력하세요." })</div>
            @*<div class="col-md-2"><button type="button" onclick="return fnDoubleCheck();" class="btn btn-lg btn-lgr-str">중복검사</button></div>*@
        </div>
    </div>

    <div class="field">
        @Html.TextBoxFor(m => m.MemberName, new { placeholder = "이름을 입력하세요." })
    </div>

    <div class="field">
        @Html.TextBoxFor(m => m.MemberPWD, new { placeholder = "암호를 입력하세요." })
    </div>
    <div class="field">
        @Html.TextBoxFor(m => m.Email, new { placeholder = "메일을 입력하세요." })
    </div>
    <div class="field">
        @Html.TextBoxFor(m => m.Telephone, new { placeholder = "전화번호를 입력하세요." })
    </div>
    <div class="dividewhite2"></div>
    <div class="field text-center">              
    </div>

    <div class="field text-center">
        <button type="submit" id="btnSave" onclick="return fnSaveCheck();" class="btn btn-lg btn-lgr-str">수정하기</button>
       
<button type="button" onclick="return fnDeleteConfirm();" class="btn btn-lg btn-danger btn-lgr-str">삭제하기</button>
    </div>
</form>

 //삭제확인
 function fnDeleteConfirm() {

            if (confirm("삭제하시겠습니까?") == true) {
                window.location.href = "/Member/Delete?memberid=" + $("#MemberID").val();
            } else {
                return false;
            }

   }


3)관리자가 정보를 수정 후 수정 버튼을 클릭하면 POST방식으로 전달되는 값을 컨트롤러에 액션메소드를 추가합니다.
-Edit 액션메소드를 POST타입으로 하나만들고 매개변수를 Member모델을 전달받습니다.
-뷰에서 전달된 모델값과 DB에 저장되어 있는 해당 사용자의 정보가 시점상에 문제로 상이할수 있으므로
사용자의 최신정보를 다시 조회하여 뷰에서 전달된 정보로 갱신 후 DB에 수정처리합니다.
-처리 결과 메시지를 ViewBag Result속성에 정의하여 뷰에 전달합니다.

 [HttpPost]
 public ActionResult Edit(Member member)
 {
            Member dbMember = db.Member.Find(member.MemberID);
            try
            {
                dbMember.MemberName = member.MemberName;
                dbMember.MemberPWD = member.MemberPWD;
                dbMember.Email = member.Email;
                dbMember.Telephone = member.Telephone;
               
                db.Entry(dbMember).State = EntityState.Modified;
                db.SaveChanges();

                ViewBag.Result = "OK";
            }
            catch (Exception ex)
            {
                ViewBag.Result = "FAIL";
            }

            return View(dbMember);
   }

4)사용자 정보를 삭제합니다.
-삭제 버튼을 클릭하면 Member컨트롤러에 Delete이란 액션메소드를 GET방식으로 호출합니다.
-호출시 사용자 아이디 값을 전달합니다.
-컨트롤러에 Delete 액션메소드를 추가하고 정보를 삭제 후 회원목록페이지로 이동합니다.

 [HttpGet]
 public ActionResult Delete(string memberid)
 {
            Member dbMember = db.Member.Find(memberid);
            db.Member.Remove(dbMember);
            db.SaveChanges();

            return RedirectToAction("List");
  }


지금까지 모델기반으로 회원가입부터 회원목록화면,페이징,수정,삭제등의 EF기반 DB프로그램의 기본적인 내용을 다루어 보았습니다.
데모솔루션은 아래 링크에서 다운로드 받으세요.
http://mixedcode.com/upload/EddyHomePageSolution.zip


이후 2차교육 및 출간서적에서는  EF 모델기반 DB 프로그래밍 응용편 과 OPEN API 기술들을 좀더 다뤄 보도록 하겠습니다.

ㅁ EF 모델 기반 DB 프로그래밍2(응용)
A.게시글 등록/수정하기
-파일업로드
B.게시판 목록 개발하기
-PagedList MVC 서버 페이징 컨트롤 사용하기
C.게시글 정보 확인하기
D.게시글 삭제하기
E.메일링 발송하기

ㅁ EF 모델 기반 DB 프로그래밍3(OPEN API 기술활용하기)
-AJAX기반 프로그래밍
-WEB API 기술소개
-WEB API 기반 CRUD 처리

감사합니다.







Comments

Leave a Reply

*