Entity Framework
Entity Framework (EF)은 C#과 같은 객체 지향형 프로그래밍(OOP) 언어에서 데이타베이스를 쉽게 사용하기 위한
ORM (Object-Relational Mapping) 도구로서, OOP의 객체(Object)와 관계형(Relational) DB의 테이블을 매핑(Mapping)하여
(ADO.NET에서 처럼 별도의 SQL 쿼리를 작성하지 않고도) 쉽게 데이타를 엑세스할 수 있게한다.
Microsoft가 직접 구현한 ORM (Object-Relational Mapping) 기술로는 Entity Framework (EF)과 LINQ TO SQL이 있으며,
이외에 NHibernate, Dapper 같은 .NET용 ORM 오픈소스들이 있다.
Entity Framework은 데이타베이스를 엑세서하는 기술이므로 ASP.NET에서만 사용하는 것은 아니지만,
ASP.NET MVC에서 데이타를 엑세스하는 기본 프레임워크로 Entity Framework을 사용하기 때문에
MVC를 사용하면 Entity Framework를 자연스럽게 사용하게 된다.
Entity Framework 버전
Entity Framework v1.0은 2008년 .NET 3.5 SP1에 포함되어 처음 발표되었고, 이후 .NET 4.0에 Entity Framework v4.0 이 발표되었다.
2012년 .NET 4.5가 발표되면서 EF v5.0 이 발표되었고, 2013년 Entity Framework v6.0이 (기존 .NET에 포함시키지 않고) 오픈소스로 발표되었다.
이후 Entity Framework 7.0은 ASP.NET Core에서와 같이 Windows, Linux, OS 등 크로스 플랫폼에서 사용할 수 있도록 Scope를 변경하였으며,
명칭을 Entity Framework Core 1.0으로 변경하였다.
현재 MVC5에서 사용하는 것은 Entity Framework v6.0이다.
ASP.NET MVC 프로젝트를 새로 생성하면 (템플릿 선택에 따라 다르지만) 보통 Entity Framework이 포함되는 경우가 많지만, 일부 옵션에서
Entity Framework v6.0이 없는 경우가 있을 수 있다.
만약 ASP.NET 프로젝트에 EFv6가 없는 경우,
Visual Studio에서 Tools -> Nuget Package Manager -> Package Manager Console 을 선택하고 아래와 같이 EFv6 패키지를 설치한다.
PM> Install-Package EntityFramework
현재 EF가 설치되어 있는지는
Solution Explorer의 References 에서 EntityFramework 이 있는지 확인할 수 있으며,
속성창에서 EntityFramework의 Version이 6.0 인지 확인한다 (주: Runtime Version이 아니라 Version).
Entity Framework 모델
Entity Framework은 크게 3가지의 접근 모델이 있는데, (1) Code First (2) Model First (3) Database First 모델이 그것이다.
이 중 Model First와 Database First 접근 모델은 Visual Studio의 Visual Model Designer (EDMX)를 통해 객체/테이블 매핑을
디자인하는 방식으로, Database First 접근 모델은 기존 DB로부터 테이블 구조들을 읽어 Visual Model을 구성하는 것이고,
Model First는 기존 DB가 없을 때 직접 Visual Model Designer에 Entity 들을 하나씩 추가해 가면서 데이타 모델을 구성하는 방식이다.
이들 Model First / Database First 방식은 Visual Model Designer에 디자인한 것을 *.edmx 라는 파일에 저장하게 된다.
Code First 접근 방식은 Visual Model Designer / EDMX 를 사용하지 않고 데이타 모델을 C# 클래스로 직접 코딩하는 방식으로
향후 Entity Framework은 Code First 모델만을 지원할 것이므로 (주: EFv6는 3개 모두 지원하고 있음) 여기서는 Code First 방식만을 설명한다.
Code First
Code First는 먼저 C# 클래스로 테이블의 구조를 정의하는데, 클래스의 속성을 테이블의 컬럼에 매핑한다.
Code First라는 말에서 처럼 이 접근 방식은 DB를 미리 설계하지 않고 C# 클래스들로 Domain Object들을 정의하고
프로그램 실행시 DB가 없으면 자동으로 DB를 생성하는 방식을 취한다. (주: 기업 환경에서는 DB 팀이 별도로 있거나
정교한 DB 설계를 미리 하는 경우가 많다. 이런 경우 기존 DB 구조와 매핑하는 C# 클래스들을 정의하고 DB 생성 없이 사용한다.)
아래 예제는 방명록을 위한 Guest라는 클래스를 정의하고 있는데, 클래스의 각 속성들은 Guest 라는 테이블에 1 대 1로 매핑된다.
이렇게 간단한 속성들로 정의되어 외부 Framework에 의존하지 않는 단순한 Entity 클래스를 POCO (Plain Old CLR Object) 클래스라 부르는데,
기본적으로 단순히 데이타를 저장했다 전달하는 역활을 한다.
using System;
using System.Data.Entity;
using System.ComponentModel.DataAnnotations.Schema;
namespace GuestBook.Models
{
public class GuestDbContext : DbContext
{
public GuestDbContext() : base()
{
}
public DbSet<Guest> Guests { get; set; }
}
[Table("Guest")]
public class Guest
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime CreateDate { get; set; }
public string Message { get; set; }
}
}
위의 GuestDbContext 클래스는 EntityFramework (System.Data.Entity)의 DbContext 클래스로부터 파생된 클래스로 DbContext 클래스의
여러 기능들을 상속받는다. GuestDbContext 생성자는 Base 클래스의 생성자를 호출하고 있는데 이를 통해 처음 GuestDbContext 객체가 생성되면
(Web.config의 정의에 따라) 기존 DB가 없는 경우 자동으로 DB를 생성하게 된다. 별도의 설정이 없이 디폴트로는 App_Data 폴더에
해당 클래스명 (GuestDbContext)을 따서 Local DB 파일 (*.mdf)를 생성한다.
마지막으로 위의 Guest 클래스 정의 위에 [Table(테이블명)] Attribute는 DB에서 생성될 테이블명을 명시적으로 지정한 것이다.
만약 이렇게 명시하지 않으면 디폴트로 클래스명을 테이블명으로 사용하는데, 일반적으로 클래스명의 복수형(예: Guests)을 테이블명으로 하기 때문에,
이를 피하기 위해서는 명시적으로 테이블명을 지정한다.
위와 같이 GuestDbContext와 Guest 클래스가 정의되면 C#의 LINQ (Language Integrated Query)를 사용하여
SELECT, INSERT, UPDATE, DELETE 등을 쉽게 할 수 있다.
아래 예제는 Controller에서 Entity Framework을 사용하는 예인데, AddGuest() 메서드에서 데이타를 INSERT 하고
ShowGuests() 에서 최근 10개의 레코드를 출력하고 있다.
// Controller의 Action 메서드들
// Guest 추가
public ActionResult AddGuest()
{
string name = Request["name"];
string msg = Request["msg"];
var db = new GuestDbContext();
Guest g = new Guest();
g.Name = name;
g.CreateDate = DateTime.Now;
g.Message = msg;
db.Guests.Add(g);
db.SaveChanges();
return RedirectToAction("ShowGuests");
}
// Guest 리스트
public ActionResult ShowGuests()
{
var db = new GuestDbContext();
// select top 10 * from guest order by id desc
List<Guest> guests = db.Guests.OrderByDescending(p => p.Id).Take(10).ToList();
return View(guests);
}
위 ShowGuests()의 마지막 부분에서 List<Guest> 타입인 guests 변수를 View(guests) 와 같이 View 메서드의 파라미터로 전달하고 있는데,
이는 모델 객체를 MVC의 View로 넘기는 방법 중의 하나이다. 이렇게 넘겨진 모델 객체는 View에서 아래와 같이 @model 로 전달된 모델 타입을
지정해 주고 (전체 네임스페이스 써야 함), View에서 Model 이라는 속성을 사용하여 해당 모델 객체를 사용한다. 아래의 경우 모델 객체가
리스트이므로 foreach에서 Model 을 Iteration하여 리스트 요소를 하나씩 꺼내 쓰고 있다.
@model List<GuestBook.Models.Guest>
<h2>Guests</h2>
@foreach (var row in Model)
{
<p>
<div>ID: @row.Id, Name: @row.Name</div>
<div>--- @row.Message</div>
</p>
}
위의 방식과 달리, 전달된 Model을 View에 바인딩해서 사용하면 편리한데, 이를 위해 다음에 소개하는
MVC HTML Helper를 이용할 수 있다.