EF Core는 C# 객체를 데이터베이스 테이블로 자동 변환해주는 강력한 ORM(Object Relational Mapping) 프레임워크입니다.
public class GameResult
{
public int Id { get; set; }
public string UserName { get; set; }
public int Score { get; set; }
}
이 클래스를 기반으로 Add-Migration 명령어를 실행하면…
📌 자동으로 테이블이 생성되며,
📌 Id 프로퍼티가 Primary Key로 지정되는 것을 확인할 수 있습니다.
도대체 어떻게 자동으로 그렇게 되는 걸까요?
EF Core에서 모델링을 정의하는 방식은 총 3가지입니다.
| 모델링 방식 | 설명 | 특징 및 용도 |
|---|---|---|
| 1. Convention | 관례 기반 | 기본 설정, 자동 처리 |
| 2. Data Annotation | 데이터 주석 기반 | 속성에 어노테이션 부여 |
| 3. Fluent API | 직접 명시하는 방식 | 세세한 제어 가능, 확장성 높음 |
public이어야 한다.static이면 안된다.nullable 여부도 자동 반영Id, 혹은 [클래스명]Id 프로퍼티는 자동으로 Primary Key가 된다.예시:
public class Book
{
public int BookId { get; set; } // 자동으로 PK 처리됨
public string Title { get; set; }
}
속성에 직접 주석을 달아 세부 설정을 제어하는 방식입니다. Blazor의 Form 유효성 검사에서도 많이 사용되었죠.
| 어노테이션 | 설명 |
|---|---|
[Key] | Primary Key 명시 |
[Required] | NOT NULL 설정 |
[MaxLength(n)] | 문자열 최대 길이 제한 |
[Column] | 컬럼명 또는 순서 설정 |
[Table] | 테이블 이름 설정 |
[NotMapped] | DB에 매핑하지 않음 |
[Table("Books")]
public class Book
{
[Key]
public int Id { get; set; }
[Required]
[MaxLength(100)]
public string Title { get; set; }
[NotMapped]
public string TempData { get; set; } // DB에는 저장되지 않음
}
복잡한 모델링 설정이나, 관례 및 주석 방식으로 표현할 수 없는 경우에 사용합니다.
DbContext의 OnModelCreating 메서드 내에서 정의합니다.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Book>()
.HasKey(b => b.Id);
modelBuilder.Entity<Book>()
.Property(b => b.Title)
.HasMaxLength(100)
.IsRequired();
modelBuilder.Entity<Book>()
.Ignore(b => b.TempData);
}
| 설정 항목 | 메서드 예시 |
|---|---|
| Primary Key | HasKey() |
| 필수 여부 | IsRequired() |
| MaxLength | HasMaxLength() |
| 테이블 이름 | ToTable("TableName") |
| 무시할 속성 | Ignore() |
| 인덱스 생성 | HasIndex().IsUnique().HasDatabaseName() |
기본 원칙! 아래 순서로 점진적으로 적용합니다.
관례(Convention)
→ 기본 설정으로 충분하면 자동 설정만으로도 무난하게 사용 가능.
데이터 주석(Data Annotation)
→ 뷰에서 재사용 가능하고 간단하게 설정 가능. 유효성 검사에도 좋음.
Fluent API
→ 복잡하거나 고급 설정이 필요할 경우 직접적으로 설정.
| 방식 | 적용 예시 |
|---|---|
| 데이터 주석 방식 | [NotMapped] |
| Fluent API 방식 | .Ignore(p => p.PropertyName) |
사용 목적: DB에는 저장하지 않지만, C# 메모리에서는 사용하고 싶은 경우
modelBuilder.Entity<Book>()
.HasIndex(b => b.Title)
.IsUnique()
.HasDatabaseName("IX_Title");
| 방식 | 예시 |
|---|---|
| Convention | DbSet<Book> → 테이블명은 Books |
| Data Annotation | [Table("LibraryBooks")] |
| Fluent API | .ToTable("LibraryBooks") |