Entity Framework Core
Entity Framework Core는 Microsoft의 ORM 기술로 Code First로 표현되는 C#의 클래스를 기반으로 데이터베이스를 구성하는 방법을 제공합니다.
이번 강의에서는 Entity Framework Core에 대해 배워보겠습니다. Entity Framework Core는 .NET Core 기반의 ORM 프레임워크로, 데이터베이스와 객체 간의 매핑을 쉽게 처리할 수 있도록 도와줍니다.
이 강의에서는 Entity Framework Core의 기본 개념과 사용 방법, 데이터베이스 마이그레이션, 관계 설정 등에 대해 배우고, 실제 예제를 통해 개발해보며 Entity Framework Core의 다양한 기능을 익힐 예정입니다.
이 강의를 통해 Entity Framework Core를 사용하여 .NET Core 애플리케이션을 더욱 효율적으로 개발할 수 있도록 준비해보세요!
EF Core 버전
아래는 Entity Framework Core 버전별 요약 표입니다.
버전 | 출시 연도 | 주요 변경 내용 |
---|---|---|
EF Core 1 | 2016 | 초기 버전, 코드 기반 데이터베이스 마이그레이션(code-based database migration) 등 추가 |
EF Core 2 | 2017 | 성능 향상, LINQ에 like 연산자 지원 등 추가 |
EF Core 3 | 2019 | LINQ에 Intersect, Except 연산자 지원, Cosmos DB 지원 등 추가 |
EF Core 5 | 2020 | 성능 향상, LINQ 지원 개선, 새로운 데이터베이스 엔진 지원 등 추가 |
EF Core 6 | 2021 | 일관성 있는 API, 기능 개선, 성능 향상, JSON 열 지원, Entity Framework 6 호환 모드 등 추가 |
Code First vs Database First
ORM(Object Relational Mapper)과 EF Core
ORM(Object-Relational Mapping)
은 OOP 프로그래밍 언어와 관계형 데이터베이스 간의 데이터 매핑을 자동으로 처리하는 프레임워크나 라이브러리를 의미합니다.
ORM을 사용하면 데이터베이스 스키마를 클래스와 개체로 매핑하여 데이터를 관리할 수 있습니다. ORM을 사용하면 일반적인 SQL 쿼리를 작성하는 대신, 개체를 사용하여 데이터를 가져오거나 업데이트할 수 있습니다. ORM은 데이터베이스와 개체 사이의 매핑을 추상화하여 개체를 사용하여 데이터베이스를 다루는 것을 가능하게 해줍니다.
.NET 환경에서 ORM을 사용하면, 데이터베이스와 개체 간의 매핑을 쉽게 처리할 수 있습니다. Entity Framework Core는 .NET 환경에서 가장 많이 사용되는 ORM 프레임워크 중 하나입니다.
Entity Framework Core는 개발자가 개체지향적인 방식으로 데이터베이스를 다룰 수 있도록 도와줍니다. Entity Framework Core는 다양한 기능을 제공하여 데이터베이스와 개체 간의 매핑을 자동으로 처리할 수 있습니다. 예를 들어, Entity Framework Core는 데이터베이스 스키마를 코드로 변환하여 클래스와 개체에 매핑할 수 있습니다. 이를 통해 개발자는 SQL 쿼리 작성 없이도 데이터베이스를 조작할 수 있습니다.
Entity Framework Core는 ORM 프레임워크의 표준적인 기능인 CRUD(Create, Read, Update, Delete)
를 제공합니다. Entity Framework Core를 사용하면, 개발자는 일반적인 데이터베이스 작업을 쉽게 처리할 수 있습니다. 또한, Entity Framework Core는 LINQ(Language Integrated Query)를 지원하여, 개발자가 개체를 사용하여 데이터를 검색할 수 있도록 도와줍니다.
Entity Framework Core는 다양한 데이터베이스 시스템과 호환됩니다. Entity Framework Core는 다양한 데이터베이스 시스템을 지원하며, 사용자 정의 데이터베이스 시스템을 만들 수 있습니다. 또한, Entity Framework Core는 다양한 데이터베이스 시스템에서의 데이터베이스 이관 작업을 지원하여, 데이터베이스를 쉽게 이관할 수 있도록 도와줍니다.
Entity Framework Core는 또한 성능을 개선하기 위한 다양한 기능을 제공합니다. Entity Framework Core는 쿼리 최적화, 레이지 로딩(Lazy Loading), 캐싱 등의 기능을 제공하여, 데이터베이스 처리 성능을 개선할 수 있습니다.
이러한 이유로 Entity Framework Core는 .NET 환경에서 가장 많이 사용되는 ORM 프레임워크 중 하나입니다.
EF Core 설치
Entity Framework Core는 NuGet 패키지 관리자를 통해 간단하게 설치할 수 있습니다.
아래는 Entity Framework Core 패키지를 설치하는 방법입니다.
.NET Core 프로젝트 생성
Entity Framework Core를 사용하려면, .NET Core 프로젝트가 필요합니다. .NET Core 프로젝트는 Visual Studio 또는 .NET Core CLI(Command Line Interface)를 통해 생성할 수 있습니다.
NuGet 패키지 관리자에서 Entity Framework Core 패키지 설치
NuGet 패키지 관리자에서 Entity Framework Core 패키지를 설치할 수 있습니다. Visual Studio에서는 NuGet 패키지 관리자를 통해 쉽게 설치할 수 있습니다. 또한, .NET Core CLI를 사용하여 명령어를 통해 패키지를 설치할 수도 있습니다.
dotnet add package Microsoft.EntityFrameworkCore
Entity Framework Core 패키지 사용
Entity Framework Core 패키지를 성공적으로 설치한 후, 해당 패키지를 사용할 수 있습니다. 데이터베이스와의 연결, 데이터 검색 및 삽입, 데이터 마이그레이션 등을 Entity Framework Core를 통해 처리할 수 있습니다.
이렇게 간단하게 Entity Framework Core를 설치하고 사용할 수 있습니다. 다음 강의에서는 Entity Framework Core의 기본 개념과 사용 방법에 대해 자세히 알아보겠습니다.
EF 도구 설치
dotnet tool install dotnet-ef --global --version 7.0.0
dotnet-ef --version
dotnet ef --version
데이터베이스 처리 관련 API 집합체
C#(.NET) 환경에서 데이터베이스 처리를 위한 API 집합체는 크게 3가지가 있습니다.
- ADO.NET A. SqlConnection B. SqlCommand C. SqlDataReader D. SqlDataAdapter E. DataSet
- Dapper A. Micro ORM B. LINQ
- Entity Framework Core A. ORM B. .NET Standard
5 Entity Framework Core 관련 필수 패키지(닷넷 스탠다드)
5.1 ASP.NET Core와 .NET Standard 프로젝트에 Entity Framework Core 설정
.NET Core 환경에서 EF Core를 사용하기 위한 가장 완벽한 NuGet 패키지 설치 리스트는 다음과 같습니다. SQL Server 데이터베이스 엔진에 접근할 때에는 Microsoft.EntityFrameworkCore.SqlServer 패키지가 반드시 필요합니다.
- Install-Package Microsoft.EntityFrameworkCore
- Install-Package Microsoft.EntityFrameworkCore.SqlServer
- Install-Package Microsoft.EntityFrameworkCore.Tools
- Install-Package System.Configuration.ConfigurationManager
- Install-Package Microsoft.Data.SqlClient
- Install-Package System.Data.SqlClient (구버전)
다음은 .NET CLI를 사용한 패키지 설데 예시 코드입니다.
dotnet add package Microsoft.EntityFrameworkCore.SqlServer --version 7.0.0
5.1.1 닷넷 스탠다드에 Dapper와 EF Core 관련 누겟 패키지 설치
- PM> Install-Package Dapper
- PM> Install-Package Microsoft.EntityFrameworkCore
- PM> Install-Package Microsoft.EntityFrameworkCore.SqlServer
- PM> Install-Package System.Configuration.ConfigurationManager
5.1.2 EntityFrameworkCore 설치: 패키지 관리자 콘솔
PM> Install-Package Micrsoft.EntityFrameworkCore.SqlServer
5.2 Entity Framework Core 관련 필수 패키지 2개 또는 3개
닷넷 스탠다드 프로젝트와 이를 사용하는 프로젝트에 Microsoft.EntityFrameworkCore.dll 파일을 추가합니다.
> Install-Package Microsoft.EntityFrameworkCore
닷넷 스탠다드 프로젝트에 Microsoft.EntityFrameworkCore.SqlServer.dll 파일을 추가합니다.
> Install-Package Microsoft.EntityFrameworkCore.SqlServer
.NET Core가 아닌 .NET Framework에서 실행하게 하려면 System.Configuration.ConfigurationManager.dll 파일도 NuGet에서 추가로 다운로드 받아야 합니다.
추가로 Tools를 설치합니다.
> Install-Package Microsoft.EntityFrameworkCore.Tools
5.3 콘솔 응용 프로그램에서 EF Core 사용하기
콘솔 응용 프로그램에서 EF Core를 위한 필수 패키지는 다음 그림과 같습니다.
그림: Entity Framework Core 사용을 위한 필수 NuGet 패키지
6 EF Core 학습을 위한 쇼핑몰 관련 모델 클래스 구성
7 Entity Framework Core에서 가장 많이 사용하는 명령어
다음 2개 또는 3개의 EF Core 명령어는 가장 많이 사용되는 명령어입니다. Add-Migration은 모델 클래스와 DbContext를 바탕으로 테이블 구조를 만들기 위한 기본 데이터베이스 스키마를 만드는 작업이고, Update-Database는 실제 데이터베이스와 테이블을 만드는 작업을 진행합니다. 추가로, Script-Migration은 모델을 바탕으로 실제 생성되는 SQL Script 구문을 생성합니다. 이 생성된 구문을 통해서 직접 데이터베이스에 적용할 수 있습니다. 개발환경에서는 Update-Database로 직접 스키마를 생성하고 프로덕션환경에서는 Script-Migration을 통해서 직접 필요한 작업을 수행하면 됩니다.
PM> Add-Migration "Initial Create"
PM> Update-Database
PM> Script-Migration
dotnet ef dbcontext --help
Add-Migration
뒤에는 마이그레이션 이름을 문자열로 작성하면 됩니다. 공백없는 문자열일 경우 큰따옴표는 생략할 수 있습니다.
참고로 DbContext
의 HasData()
메서드는 데이터베이스에 초깃값(Seed)을 줄 때 사용됩니다.
8 Entitiry Framework Core 관련 핵심 클래스 3가지
DbContext
DbContextOptions
DbSet<T>
9 DbContext 기본 클래스
DbContext
기본 클래스를 사용하여 데이터베이스 연결
DbSet<T>
속성
9.1 Entity Framework Core를 .NET의 모든 영역에서 공통으로 사용하기
코드: 만능 데이터컨텍스트 개체
using DotNetNote.Models.Notifications;
using Microsoft.EntityFrameworkCore;
namespace DotNetNote.Models
{
public class DotNetNoteContext : DbContext
{
public DotNetNoteContext()
{
}
public DotNetNoteContext(
DbContextOptions<DotNetNoteContext> options) : base(options)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
string connectionString =
System.Configuration.ConfigurationManager
.ConnectionStrings["ConnectionString"].ConnectionString;
optionsBuilder.UseSqlServer(connectionString);
}
}
/// <summary>
/// 알림(Noti) 기능
/// </summary>
public DbSet<MyNotification> MyNotifications { get; set; }
}
}
9.2 DotNetNoteContext.cs 코드 샘플
코드샘플: DotNetNoteContext.cs 코드 샘플
//Install-Package Microsoft.EntityFrameworkCore
//Install-Package Microsoft.EntityFrameworkCore.SqlServer
//Install-Package Microsoft.EntityFrameworkCore.Tools
//Install-Package System.Configuration.ConfigurationManager
//Install-Package System.Data.SqlClient
using Microsoft.EntityFrameworkCore;
using System.Configuration;
namespace DotNetNote.Models
{
public class DotNetNoteContext : DbContext
{
public DotNetNoteContext()
{
// Empty
}
public DotNetNoteContext(DbContextOptions<DotNetNoteContext> options)
: base(options)
{
// 공식과 같은 코드
}
protected override void OnConfiguring(
DbContextOptionsBuilder optionsBuilder)
{
// 닷넷 프레임워크 기반에서 호출되는 코드 영역:
// App.Config 또는 Web.Config의 연결 문자열 사용
if (!optionsBuilder.IsConfigured)
{
string connectionString = ConfigurationManager.ConnectionStrings[
"ConnectionString"].ConnectionString;
optionsBuilder.UseSqlServer(connectionString);
}
}
/// <summary>
/// 아이디어 관리자
/// 아이디어 앱에 대한 참조(Idea 모델 클래스 <=> Ideas 테이블)
/// </summary>
public DbSet<Idea> Ideas { get; set; }
/// <summary>
/// 게시판
/// </summary>
public DbSet<Note> Notes { get; set; }
/// <summary>
/// 도메인 관리자 테이블 참조
/// </summary>
public DbSet<Url> Urls { get; set; }
/// <summary>
/// 기술 리스트: [실습] Teches 테이블부터 Angular 앱 또는 Blazor 앱까지
/// </summary>
public DbSet<Tech> Teches { get; set; }
}
}
9.3 DbContext 클래스 코드 샘플
코드: 새로운 DbContext 클래스 추가 코드 샘플
using Microsoft.EntityFrameworkCore;
using TwelveManager.Models;
namespace TwelveManager.Data
{
public class DashboardContext : DbContext
{
public DbSet<Twelve> Twelves { get; set; }
/// <summary>
/// 생성자 매개변수에 옵션값 전달
/// </summary>
public DashboardContext(DbContextOptions<DashboardContext> options)
: base(options)
{
}
}
}
// Startup.cs 파일에 DbContext 추가 코드 샘플
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is ne
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<IdentityUser>()
.AddDefaultUI(UIFramework.Bootstrap4)
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
// 새로운 DbContext 추가
services.AddEntityFrameworkSqlServer().AddDbContext<DashboardContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
}
9.4 EF Core 코드 조각
// EF DB Context를 ConfigureServices에 추가하기
services.AddDbContext<XxxContext>(ServiceLifetime.Scoped);
10 InMemoryDatabase 미들웨어 사용 빠른 CRUD 테스트
- 모델 및 컨텍스트 클래스 생성
// /DotNetNote/Components/TodoComponent.cs
using Microsoft.EntityFrameworkCore;
namespace DotNetNote.Components
{
public class TodoComponent
{
// Empty
}
/// <summary>
/// Todo 모델 클래스: Todos 테이블과 일대일로 매핑
/// </summary>
public class Todo
{
public int Id { get; set; }
public string Title { get; set; }
public bool IsDone { get; set; } = false;
}
/// <summary>
/// Todo 컨텍스트 클래스
/// </summary>
public class TodoContext : DbContext
{
public TodoContext(DbContextOptions<TodoContext> options) : base(options)
{
// Empty
}
public DbSet<Todo> Todos { get; set; }
}
public interface ITodoRepository
{
}
public class TodoRepository : ITodoRepository
{
}
}
- Startup.cs 파일에 컨텍스트 등록
// ConfigureServices() 메서드
public void ConfigureServices(IServiceCollection services)
{
//[!] 인-메모리 DB를 가상으로 만들어서
// TodoContext에서 지정한 모델 클래스 구조로 DB CRUD 구현 가능
services.AddDbContext<TodoContext>(
options => options.UseInMemoryDatabase("DotNetNote"));
services.AddMvc();
}
// Configure() 메서드에 임시 데이터 등록
public void Configure(
IApplicationBuilder app,
IWebHostEnvironment env,
IServiceProvider serviceProvider)
{
var todo = serviceProvider.GetService<TodoContext>();
todo.Todos.Add(new Todo { Id = 1, Title = "Angular", IsDone = false });
todo.Todos.Add(new Todo { Id = 2, Title = "ASP.NET Core", IsDone = false });
todo.SaveChanges();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
11 데이터 모델 시각화 도구
Entity Framework Core 관련 데이터 구조에 대한 모델 시각화를 구현할 때에는 기본적으로 Visual Studio 확장 기능을 사용해야 합니다. EF Core가 오픈소스로 되어 있기에 따로 Microsoft에서 관리하기 보다는 외부 커뮤니티에 맡기는 것 같습니다. 그래서 많은 유료/무료 확장 기능을 제공하고 있습니다.
11.1 EF Core 도구 및 확장
다음 링크에서 주요 EF Core 도구 및 확장 기능 목록을 살펴볼 수 있구요.
EF Core 확장 도구는 Devart와 같은 사용 도구를 사용하면 동일 수준으로 표시가 됩니다.
11.2 EF Core Power Tools
그 중에서 EF Core Power Tools를 사용하면 다음 그림과 같은 모양으로 관리를 할 수 있습니다.
11.3 클래스 다이어그램
아니면, Visual Studio에 내장되어 있는 C# 클래스 다이어그램을 사용하면 외부 확장 기능없이도 다음 느낌의 모델 시각화는 구현할 수 있습니다.
12 ASP.NET Core 프로젝트에 DbContext 추가(여러 개)
12.1 DbContext 클래스 만들기
// /ProfitManager/Data/DashboardContext.cs
using Microsoft.EntityFrameworkCore;
using ProfitManager.Models;
namespace ProfitManager.Data
{
public class DashboardContext : DbContext
{
/// <summary>
/// Profits 테이블 참조
/// </summary>
public DbSet<ProfitModel> Profits { get; set; }
/// <summary>
/// 생성자 매개변수에 옵션값 전달
/// </summary>
public DashboardContext(DbContextOptions<DashboardContext> options)
: base(options)
{
}
}
}
12.2 DbContext 클래스 등록
// /ProfitManager/Startup.cs
// 새로운 DbContext 추가
services.AddEntityFrameworkSqlServer().AddDbContext<DashboardContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
13 EF Core 코드 조각들
13.1 ExecuteSqlCommand() 메서드로 쿼리 직접 실행하기
// 기존 데이터 지우기
_context.Database.ExecuteSqlCommand("Delete ProjectsLoads Where ProjectId = " + project.Id.ToString());
13.2 특정 조건에 맞는 여러 레코드를 한꺼번에 삭제하기
// 기존 ParentId에 해당하는 모든 레코드 삭제
_context.Profits.Where(p => p.ParentId == parentId).ToList().ForEach(p => _context.Profits.Remove(p));
_context.SaveChanges();
13.3 수정: EntityState.Modified
_context.Entry(customer).State = EntityState.Modified;
_context.SaveChanges();
14 인-메모리에서 SQL Server 등 테스트
닷넷 스탠다드 2.0 또는 MSTest 테스트 프로젝트에서 다음 이름의 NuGet 패키지의 2.X 버전대를 설치합니다. 3.X 버전대를 사용하려면 닷넷 스탠다드 2.1이 필요하여 ASP.NET Core 이외에는 접근이 불가능합니다.
- Microsoft.EntityFrameworkCore.InMemory
[실습] Entity Framework Core를 사용하여 콘솔에서 CRUD 작업
소개
따라하기 1: 프로젝트 생성
따라하기 2:
마무리
EF Core를 사용하여 관련 테이블 데이터를 가져오기
이 아티클에서는 EF Core를 사용하여 관련 테이블 데이터를 가져오는 방법에 대해 설명합니다. 아래 예제에서는 'Broth', 'Noodle' 및 'Garnish'라는 세 가지 모델 클래스를 사용하여 데이터를 조인하여 가져옵니다.
참고로, 이 세 가지 모델 클래스는 Blazor Server 7.0 Fundamentals 강의 소스에 포함된 내용입니다.
- 모델 클래스 정의:
이 예제에서는 이미 세 가지 모델 클래스가 정의되어 있습니다. Broth
, Noodle
, Garnish
클래스는 각각 국물, 국수, 고명에 대한 정보를 나타냅니다. 아래 코드에서 각 클래스의 정의를 참조하십시오.
// Broth.cs
public class Broth
{
public int Id { get; set; }
// ... 다른 속성
}
// Noodle.cs
public class Noodle
{
public int Id { get; set; }
public int? BrothId { get; set; }
public Broth? Broth { get; set; }
// ... 다른 속성
}
// Garnish.cs
public class Garnish
{
public int Id { get; set; }
public int? NoodleId { get; set; }
public Noodle? Noodle { get; set; }
// ... 다른 속성
}
- DbContext 클래스 정의:
DbContext
클래스를 정의하여 각 모델 클래스에 대한 DbSet
속성을 추가합니다.
public class BuffetDbContext : DbContext
{
public DbSet<Broth> Broths { get; set; }
public DbSet<Noodle> Noodles { get; set; }
public DbSet<Garnish> Garnishes { get; set; }
// ... 다른 구성
}
- 데이터를 가져오는 방법:
Include
메서드를 사용하여 관련 테이블 데이터를 가져올 수 있습니다. 아래 예제에서는 국수와 관련된 국물과 고명 정보를 가져오는 방법을 보여줍니다.
using (var context = new BuffetDbContext())
{
var noodlesWithBrothsAndGarnishes = context.Noodles
.Include(n => n.Broth)
.Include(n => n.Garnishes)
.ToList();
}
- 필터링 및 정렬:
Where
및 OrderBy
메서드를 사용하여 결과를 필터링하고 정렬할 수 있습니다.
using (var context = new BuffetDbContext())
{
var veganNoodlesWithBrothsAndGarnishes = context.Noodles
.Include(n => n.Broth)
.Include(n => n.Garnishes)
.Where(n => n.Broth.IsVegan)
.OrderBy(n => n.Name)
.ToList();
}
이 아티클에서는 EF Core를 사용하여 관련 테이블 데이터를 가져오는 방법을 설명했습니다. Include
메서드를 사용하면 한 번의 쿼리로 관련 테이블의 데이터를 가져올 수 있습니다. 이를 통해 국수, 국물, 고명과 같은 관련된 데이터를 쉽게 추출할 수 있습니다.
연관 데이터 가져오기
- 즉시 로딩(Eagar Loading)
- 프로젝션
- 늦은 로딩(Lazy Loading)
늦은 로딩(Lazy Loading)
EF Core의 늦은 로딩은 기본값으로 비활성화되어 있습니다.