Entity Framework

엔티티 프레임워크(Entity Framework) 1:N 관계 매핑

zorimo 2025. 1. 22. 11:15

지난 포스팅에서는 Entity Framework의 1:1 관계 매핑과

DbContext의 주요 메서드인 OnConfiguring, OnModelCreating에 대해 배웠습니다.

 

이번 글에서는 1:N 관계 매핑을 살펴보고

제품(Product)과 카테고리(ProductCategory) 간의 관계를 예제로 구현하겠습니다.


1. 1:N 관계란?

1:N 관계는 한 엔티티가 여러 엔티티와 연결되는 관계를 의미합니다.

 

예를 들어 제품 카테고리(ProductCategory)에는 여러 제품들이 속하고 있고,

제품은 특정 카테고리에 속하는 경우에 해당될 수 있겠죠.

 


2. 1:N 관계 매핑

2.1 시나리오 설명

제품(Product)

- 각각의 제품은 반드시 하나의 카테고리에 속합니다.

- 따라서 Category 속성은 nullable하지 않으며, default!로 초기화합니다.

 

카테고리(ProductCategory)

- 카테고리는 독립적으로 존재할 수 있습니다.

- 하지만 카테고리에 제품이 없을 수도 있으므로, Products 속성은 nullable로 설정합니다.


2.2 모델 작성 및 수정

ProductCategory 엔티티 생성

namespace EFCoreDemo.Model;

public class ProductCategory
{
    public int Id { get; set; }

    public string Name { get; set; } = string.Empty;

    public List<Product>? Products { get; set; } // 카테고리는 제품이 없을 수도 있음
}
 

Product 엔티티 수정

namespace EFCoreDemo.Model;

public class Product
{
    public int Id { get; set; }

    public string Name { get; set; } = string.Empty;

    public int CategoryId { get; set; } // 외래 키

    public ProductCategory Category { get; set; } = default!; // 반드시 카테고리가 있어야 함

    public ProductDetail? Detail { get; set; }
}
 

2.3 관계 매핑 코드

OnModelCreating 메서드에 1:N 관계 매핑을 추가합니다.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    (...)

    modelBuilder.Entity<Product>()
                .HasOne(p => p.Category)                  // Product는 하나의 Category를 가짐 
                .WithMany(c => c.Products)                // Category는 여러 Product를 가짐 
                .HasForeignKey(p => p.CategoryId);        // 외래 키를 Product.CategoryId로 설정
}

3. 관계 매핑 적용 후 마이그레이션

이번 작업에서는 마이그레이션 적용 전에 기존 데이터베이스초기화해야 합니다.

터미널에 아래 명령어를 실행하세요.

dotnet ef database drop
 

메시지가 출력되면 y를 입력해 데이터베이스를 삭제합니다.


3.1 DbContext 업데이트

DbSet을 추가하여 ProductCategory 관리합니다.

public DbSet<ProductCategory> ProductCategories { get; set; } = default!;
 

3.2 마이그레이션 생성 및 적용

변경 사항을 반영하기 위해 아래 명령어를 실행합니다.

dotnet ef migrations add AddProductCategoryRelation
dotnet ef database update

4. 데이터 추가 및 확인

5.1 데이터 추가

1:N 관계를 확인하기 위해 SeedDatabase 메서드를 수정합니다.

static void SeedDatabase()
{
    using var context = new EFCoreDemoDbContext();

    // 기존 데이터 삭제
    if (context.Products.Any())
    {
        context.Products.RemoveRange(context.Products);
        context.ProductCategories.RemoveRange(context.ProductCategories);
        context.SaveChanges();
        Console.WriteLine("기존 데이터가 삭제되었습니다.");
    }

    // 새로운 카테고리 추가
    var electronics = new ProductCategory { Name = "Electronics" };
    var accessories = new ProductCategory { Name = "Accessories" };

    // 새로운 데이터 추가
    context.Products.AddRange(
        new Product
        {
            Name = "Laptop",
            Category = electronics,
            Detail = new ProductDetail
            {
                Price = 1500,
                Description = "A powerful gaming laptop"
            }
        },
        new Product
        {
            Name = "Tablet",
            Category = electronics,
            Detail = new ProductDetail
            {
                Price = 800,
                Description = "A lightweight tablet for reading"
            }
        },
        new Product
        {
            Name = "Smartphone",
            Category = electronics,
            Detail = new ProductDetail
            {
                Price = 1200,
                Description = "A flagship smartphone with excellent camera"
            }
        },
        new Product
        {
            Name = "Headphones",
            Category = accessories,
            Detail = new ProductDetail
            {
                Price = 200,
                Description = "Noise-canceling headphones"
            }
        }
    );

    context.SaveChanges();
    Console.WriteLine("새로운 데이터가 성공적으로 추가되었습니다.");
}
 

5.2 데이터 확인

모든 제품과 카테고리를 출력하는 메서드를 추가합니다.

static void ReadAllProducts()
{
    using var context = new EFCoreDemoDbContext();

    var products = context.Products
                          .Include(p => p.Category)
                          .ToList();

    Console.WriteLine("제품 목록");
    foreach (var product in products)
    {
        Console.WriteLine($"Name: {product.Name}, Category: {product.Category.Name}");
    }
}
 
 

5.3 결과

기존 데이터가 삭제되었습니다.
새로운 데이터가 성공적으로 추가되었습니다.
제품 목록
Name: Laptop, Category: Electronics
Name: Tablet, Category: Electronics
Name: Smartphone, Category: Electronics
Name: Headphones, Category: Accessories

6. 마치며

이번 글에서는 1:N 관계 매핑과 이를 구현하는 방법을 살펴보았습니다.

1:N 관계는 데이터베이스에서 가장 자주 사용되는 관계 중 하나로,

제품과 카테고리 간의 관계를 설정하는 예제를 통해 이해할 수 있었습니다.

 

다음 포스팅에서는 N:N 관계 매핑을 학습하며, 학생(Student)과 강의(Course) 간의 관계를 다룰 예정입니다.