Skip to main content

Command Palette

Search for a command to run...

EF Core 6 배우기 - 2. 엔터티

Published
3 min read

EF Core는 엔터티 클래스로 ORM의 규칙을 적용해 모델을 작성합니다. 규칙은 특성을 통해 부여하거나 EF Core에서 약속한 구성으로 만들 수 있습니다. 또한 DB 컨텍스트에서 Fluent API 방식으로 규칙을 정의할 수도 있습니다.

엔터티

엔터티는 컨텍스트에 DBSet으로 포함되면 EF Core의 모델에 포함됩니다. 일반적으로 이러한 형식을 엔터티라 합니다. 엔터티는 데이터베이스에 적용될 때 테이블 단위가 됩니다.

| 엔터티 클래스 정의

public class UserInfo
{
...
}

| 엔터티 클래스를 엔터티로 등록

public class MyContext : DbContext
{
...
    public DbSet<UserInfo> Users { get; set; }

이외에 엔터티가 되는 경우는 다음과 같습니다.

  • 엔터티에 탐색 속성으로 정의될 경우

    public class UserInfo
    {
    ...
      public List<UserHistory> Histories { get; set; }
    ...
    

    UserHistoryUserInfo와 1대 N의 관계가 형성되어 탐색 대상이 되기 때문에 엔터티 입니다.

  • 컨텍스트의 OnModelCreating()에 엔터티로 지정될 경우

    public class MyContext : DbContext
    {
    ...
      protected override void OnModelCreating(ModelBuilder modelBuilder)
      {
          modelBuilder.Entity<UserAuth>();
      }
    

    UserAuth는 컨텍스트의 OnModelCreating()에서 엔터티로 지정되었기 때문에 엔터티 입니다.

엔터티 규칙

엔터티를 클래스로 표현하기 위해 특성 및 Fluent API를 이용해 규칙을 지정할 수 있습니다.

키는 엔터티를 식별할 수 있는 기준입니다. 규칙에 따라 다음은 엔터티의 키가 됩니다.

  • 속성 이름이 Id일 경우

    public class UserInfo
    {
      public string Id { get; set; } // Id는 UserInfo의 키
      ...
    }
    
  • 속성 이름이 엔터티명 + "Id"일 경우

    public class UserInfo
    {
      public string UserId { get; set; } // UserId는 UserInfo의 키
      ...
    }
    
  • [Key] 특성을 이용해 속성을 키로 지정

    public string UserHistory
    {
      [Key]
      public int Seq { get; set; } // Seq는 UserHistory의 키
      ....
    }
    
  • 컨텍스트에서 키로 지정 컨텍스트에서 Fluent API 방식으로 해당 엔터티의 키를 지정할 수 도 있습니다.

    public class MyContext : DbContext
    {
      protected override void OnModelCreating(ModelBuilder modelBuilder)
      {
          modelBuilder.Entity<Blog>()
              .HasKey(b => b.BlogId); // Blog 엔터티의 BlogId를 키로 지정
      }
    

외래키

EF Core에서 외래키는 Fluent API로 직접 지정할 수도 있지만 엔터티의 탐색 속성을 이용해 1:1 및 1:N의 관계를 나타낼 수 있어서 데이터 질의 시 유용하므로 이를 추천합니다.

| 1:1 관계

public class UserInfo
{
    [Key]
    public string Id { get; set; }

    public UserInfo(string id)
    {
        Id = id;
    }

    public UserDetail Detail { get; set; } = default!;
}

public class UserDetail
{
    [Key]
    [ForeignKey(nameof(User))]
    public string Id { get; set; } = default!;

    public string Address { get; set; } = default!;

    public UserInfo User { get; set; } = default!;
}

여기서 UserInfoDetail 속성은 탐색 속성이 됩니다. UserDetailUser 속성은 관계 속성이 됩니다. EF Core에서는 관계 속성과 탐색 속성을 통해 관계된 다양한 질의를 할 수 있게 됩니다.

| 1:N 관계

public class UserInfo
{
    [Key]
    public string Id { get; set; }

    public UserInfo(string id)
    {
        Id = id;
    }

    public IList<Todo> Todos { get; set; } = default!;
}

public class Todo
{
    [Key]
    public int Seq { get; set; }

    public UserInfo User { get; set; } = default!;
}

할 일을 예로 들어 봅시다. 사용자 한명은 여러 개의 할 일을 가질 수 있으므로 UserInfoTodo는 1:N 관계 입니다. 이는 UserInfoTodos 탐색 속성을 통해 목록으로 정의할 수 있고 질의할 수 있습니다. 하나의 할 일은 사용자 한명에게 할당되므로 TodoUser 관계 속성으로 정의하고 질의할 수 있습니다.

이런 엔터티 관계를 통해 다음의 SQLite 테이블 및 컬럼이 생성됩니다.

image.png

정리

EF Core의 엔터티에 대해 간략히 소개하였습니다. 좀 더 자세한 내용은 마이크로소프트 문서의 모델 만들기를 통해 살펴보실 수 있습니다.

다음 시간에는 할 일 모델링을 EF Core를 이용해 엔터티와 DB 컨텍스트로 구성해서 콘솔 애플리케이션으로 그 동작을 같이 확인해보도록 합시다.

More from this blog

개발, 테스트, 운영에서의 도커 활용

핵심 원칙: "한 번 빌드하고, 어디서든 실행한다 (Build once, run anywhere)" 도커의 가장 큰 장점은 환경 일관성입니다. 동일한 도커 이미지를 사용하여 개발, 테스트, 운영 환경을 구성함으로써 "제 PC에서는 됐는데..." 하는 문제를 최소화할 수 있습니다. 1. 개발 단계 (Development) 목표: 빠른 코드 변경 반영, 쉬운 디버깅, 실제 운영 환경과 유사한 환경 구성. Docker 사용 방안: Dockerf...

May 9, 20256 min read15

[EF Core] 데이터 삭제 시 소프트 삭제 적용

DB에서 데이터를 삭제하면 일반적으로 복구할 수 없습니다. 또한 관계에 따라 영구 삭제 자체가 어려울 수도 있습니다. 그래서 데이터를 영구 삭제하는 대신 IsDeleted 속성을 true로 주고 IsDeleted 속성을 필터링해서 조회하는 방법을 사용하기도 합니다. 이를 소프트 삭제라고 합니다. 그런데 EF에서 알아서 데이터 삭제 시 소프트 삭제를 하고 쿼리시 IsDeleted 속성을 체크해서 삭제한 데이터를 제외한 데이터만 쿼리하게 하는 ...

Mar 18, 20243 min read19

[EF Core] ValueConverter를 이용해서 엔터티 속성의 도메인 관리

EF Core를 사용하면서 문자열 길이 등의 특성을 일일이 지정하는 것은 번거롭습니다. ... [MaxLength(32)] public string? 제목 { get; set; } 엔터티가 한 개일 때는 상관이 없으나 제목 유형이 여러 엔터티에 사용될 경우 유형을 지정하기 번거롭습니다. 속성 유형을 도메인으로 관리하면 참 편할텐데요, ValueConverter를 이용할 수 있습니다. 그런데 이것을 인터페이스 정적 추상를 사용해서 다음처럼 ...

Mar 16, 20242 min read8

디모이 블로그

154 posts

.NET 관련 기술을 선호하고 새로운 언어를 배우는데 관심이 있습니다.