EF Core 8.0 시작하기

  • 34 minutes to read

이 글에서는 콘솔 프로젝트에서 Entity Framework Core(EF Core)를 활용하여 데이터베이스 테이블에서 데이터를 입력, 조회, 수정, 삭제하는 기본적인 예제를 소개합니다.

Entity Framework Core 8.0 맛보기

개요

이 가이드는 .NET Core와 Entity Framework Core를 사용하여 StateTribe 엔터티가 포함된 콘솔 애플리케이션 HawasoTribe를 만드는 방법을 단계별로 설명합니다. 이 프로젝트를 통해 EF Core에 대한 기본적인 학습을 할 수 있으며, Microsoft SQL LocalDB를 사용하여 데이터베이스 작업을 수행하는 방법을 배울 수 있습니다.

사전 요구 사항

  • 선수 학습

    • ADO.NET Fundamentals 강의
  • 필요 소프트웨어

    • Visual Studio
    • .NET Core SDK

새 프로젝트 만들기

  1. Visual Studio에서 프로젝트 생성
    • Visual Studio를 열고 "새 프로젝트 만들기"를 클릭합니다.
    • "C# 콘솔 앱(.NET Core)"을 선택하고 "다음"을 클릭합니다.
    • 프로젝트 이름에 "HawasoTribe"를 입력하고 "만들기"를 클릭합니다.

Entity Framework Core 설치 및 설정

  1. EF Core 및 SQL Server 패키지 설치

    • EF Core를 사용하기 위해, Visual Studio의 "도구 > NuGet 패키지 관리자 > 패키지 관리자 콘솔"을 통해 필요한 패키지를 설치합니다.

    • 먼저, Microsoft.EntityFrameworkCore.SqlServer 패키지를 설치합니다. 콘솔에서 다음 명령어를 실행하세요:

      Install-Package Microsoft.EntityFrameworkCore.SqlServer
      
    • EF Core 사용에 필수적인 패키지들은 다음과 같습니다. 이들은 프로젝트의 필수 구성 요소로, 프로젝트 파일(.csproj)에 아래와 같이 추가할 수 있습니다:

    <ItemGroup>
      <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.1" />
      <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.1" />
      <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.1" />
    </ItemGroup>
    

    이 패키지들은 각각 다음과 같은 역할을 합니다:

    • Microsoft.EntityFrameworkCore.SqlServer: SQL Server를 위한 EF Core 지원을 추가합니다.
    • Microsoft.EntityFrameworkCore.Design: EF Core에서 데이터베이스 설계와 관련된 기능을 제공합니다.
    • Microsoft.EntityFrameworkCore.Tools: 마이그레이션 및 데이터베이스 스키마 관리를 위한 툴을 제공합니다.

    설치가 완료되면, EF Core를 사용하여 데이터베이스 작업을 진행할 준비가 완료됩니다.

    • 추가적으로, .NET Core CLI를 사용하는 경우 dotnet add package 명령을 통해 필요한 패키지를 설치할 수 있습니다. 예를 들어, 아래의 명령을 통해 필요한 패키지를 추가할 수 있습니다:

      dotnet add package Microsoft.EntityFrameworkCore.SqlServer
      dotnet add package Microsoft.EntityFrameworkCore.Design
      dotnet add package Microsoft.EntityFrameworkCore.Tools
      

      이 방법을 사용하면, 프로젝트 파일(.csproj)에 자동으로 필요한 패키지 참조가 추가됩니다.

모델 클래스와 DbContext 클래스

Entity Framework Core (EF Core)는 Microsoft가 개발한 최신 데이터 액세스 기술로, ADO.NET을 기반으로 한 Object-Relational Mapping (ORM) 프레임워크입니다. EF Core와 ADO.NET의 주요 차이점은 개발 접근 방식과 필요한 준비 작업에서 드러납니다.

  1. Entity Framework Core (EF Core)의 특징

    • ORM 기반: EF Core는 데이터베이스 테이블을 개체로 매핑하는 ORM 프레임워크입니다. 이를 통해 개발자는 SQL 쿼리를 직접 작성하는 대신, 개체 지향적 방식으로 데이터를 관리할 수 있습니다.
    • DbContext 클래스: EF Core에서는 데이터베이스와의 상호작용을 관리하기 위해 DbContext 클래스를 사용합니다. 이 클래스는 데이터베이스 세션을 대표하며, 쿼리 및 트랜잭션 처리를 담당합니다.
    • Code-First 접근법: EF Core는 코드를 통해 데이터베이스 스키마를 정의하고 관리하는 Code-First 접근법을 지원합니다.
    • 마이그레이션 기능: 소스 코드의 변경에 따라 데이터베이스 스키마를 자동으로 업데이트하는 마이그레이션 기능을 제공합니다.
    • LINQ 지원: EF Core는 LINQ를 사용하여 데이터베이스 쿼리를 더 직관적이고 편리하게 작성할 수 있게 지원합니다.
  2. ADO.NET의 특징

    • 직접적인 데이터베이스 접근: ADO.NET은 데이터베이스에 직접 접근하는 전통적인 방식을 제공합니다. 여기서는 SQL 쿼리를 수동으로 작성하고 실행합니다.
    • 데이터베이스 커넥션 관리: SqlConnection, SqlCommand 등의 클래스를 통해 데이터베이스 연결을 관리하고, SQL 쿼리를 실행합니다.
    • 성능 최적화: ADO.NET은 ORM보다 저수준에서 작업을 처리하기 때문에 성능을 세밀하게 최적화할 수 있습니다. 이는 특히 대규모 시스템이나 성능이 중요한 애플리케이션에 유용합니다.
    • 유연성: 더 복잡하나 특화된 데이터베이스 작업을 위해 높은 수준의 유연성을 제공합니다.

결론적으로, EF Core는 개발자가 개체 지향적 방식으로 데이터베이스 작업을 수행할 수 있도록 지원하며, 코드의 간소화와 데이터베이스 관리의 편리함을 제공합니다. 반면, ADO.NET은 더 세밀한 데이터베이스 제어가 가능하며, 복잡하거나 특수한 요구 사항에 유연하게 대응할 수 있습니다. EF Core를 사용하기 위해서는 초기 설정, DbContext 클래스의 구현, 마이그레이션 관리 등의 추가적인 작업이 필요하지만, 이를 통해 장기적인 생산성과 유지보수 측면에서의 이점을 얻을 수 있습니다.

모델 클래스와 DbContext 코드 조각

아래 코드 조각은 간단한 예제로, StateTribe 모델 클래스를 정의하고, TribeDbContext를 통해 데이터베이스 컨텍스트를 설정하는 방법을 보여줍니다.

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.EntityFrameworkCore;

namespace VisualAcademy
{
    // 모델 클래스 정의
    public class State // States 테이블
    {
        public int StateId { get; set; }
        public string Name { get; set; }
        public List<Tribe> Tribes { get; } = new List<Tribe>();
    }

    public class Tribe // Tribes 테이블
    {
        public int TribeId { get; set; }
        public string Name { get; set; }
        public int StateId { get; set; }
        public State State { get; set; }
    }

    // DbContext 클래스 정의
    public class TribeDbContext : DbContext
    {
        public DbSet<State> States { get; set; } // States 테이블
        public DbSet<Tribe> Tribes { get; set; } // Tribes 테이블 

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            string connectionString = @"Server=(localdb)\mssqllocaldb;
                Database=HawasoTribe;Trusted_Connection=True";
            optionsBuilder.UseSqlServer(connectionString);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // 데이터베이스 컨텍스트 인스턴스 생성
            using var context = new TribeDbContext();

            // 새 State 인스턴스 생성 및 추가
            var newState = new State { Name = "California" };
            context.States.Add(newState);
            context.SaveChanges();

            // State 데이터 조회 및 출력
            var states = context.States.ToList();
            foreach (var state in states)
            {
                Console.WriteLine($"State ID: {state.StateId}, Name: {state.Name}");
            }
        }
    }
}

위 코드는 Entity Framework Core를 사용하여 간단한 관계형 데이터 모델을 구축하고, 데이터를 저장 및 조회하는 과정을 보여줍니다.

모델 클래스 만들기

프로젝트 내에 'Models' 폴더를 생성하여, 이 폴더를 중심으로 프로젝트에 필요한 모든 엔터티들(모델, 테이블, DTO 등)을 통합 관리합니다. 각 엔터티는 'Product.cs', 'Customer.cs', 'Order.cs'와 같은 형식으로 클래스 파일로 추가하시면 됩니다.

  1. State와 Tribe 모델 클래스 정의
    • 프로젝트에 "Models" 폴더를 추가합니다.

    • 이 폴더 안에 State.csTribe.cs 두 개의 클래스 파일을 생성합니다.

    • 이 파일들은 Entity Framework Core를 사용하여 데이터베이스 모델을 나타내는 클래스를 포함합니다.

    • State.cs 파일에서는 Navigation 속성을 사용하는 State 클래스를 정의합니다:

      using System.Collections.Generic;
      
      public class State
      {
          public int StateId { get; set; }
          public string Name { get; set; }
          public List<Tribe> Tribes { get; } = new List<Tribe>();
      }
      
    • Tribe.cs 파일에서는 Tribe 클래스를 정의합니다:

      public class Tribe
      {
          public int TribeId { get; set; }
          public string Name { get; set; }
          public int StateId { get; set; }
          public State State { get; set; }
      }
      
    • 코드의 가독성을 향상시키기 위해, 속성과 네비게이션 속성을 분리하는 partial 클래스를 사용할 수 있습니다. 이는 클래스 구조를 명확하게 분리하는 데 도움이 됩니다. 예를 들어, State.csTribe.cs를 다음과 같이 수정할 수 있습니다:

      namespace HawasoTribe.Models;
      
      public partial class State
      {
           public int StateId { get; set; }
           public string Name { get; set; } = null!;
      }
      
      public partial class State
      {
           public virtual ICollection<Tribe> Tribes { get; set; } = new List<Tribe>();
      }
      
      namespace HawasoTribe.Models;
      
      public partial class Tribe
      {
           public int TribeId { get; set; }
           public string Name { get; set; } = null!;
           public int StateId { get; set; }
      }
      
      public partial class Tribe
      {
           public virtual State State { get; set; } = null!;
      }
      

DbContext 클래스 만들기

  1. TribeDbContext 클래스 구현
    • 프로젝트에 "Data" 폴더를 추가합니다.

    • 이 폴더 내에 TribeDbContext.cs 파일을 생성합니다.

    • TribeDbContext.cs 파일에는 다음과 같은 DbContext 클래스 코드를 작성합니다. 콘솔 기반 프로젝트에서는 기본 생성자를 사용하여 옵션을 주입하지 않고 직접 OnConfiguring 메서드에서 수작업으로 데이터베이스 연결 문자열을 지정하는 방식을 사용하겠습니다.

      using HawasoTribe.Models;
      using Microsoft.EntityFrameworkCore;
      
      namespace HawasoTribe.Data;
      
      public class TribeDbContext : DbContext
      {
           public DbSet<State> States { get; set; } = null!;
           public DbSet<Tribe> Tribes { get; set; } = null!;
      
           protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
           {
               optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Initial Catalog=HawasoTribe;Integrated Security=True");
           }
      }
      
    • 데이터베이스 연결 문자열에 대한 설명:

      • SQL Server: 예시에서는 SQL Server LocalDB를 사용합니다. 이는 개발 목적으로 로컬에서 SQL Server를 사용하는 가벼운 옵션입니다.
      • SQLite: SQLite를 사용할 때의 연결 문자열 예시는 options.UseSqlite("Data Source=mydatabase.db");입니다. SQLite는 설정이 간단하며, 파일 기반의 데이터베이스를 제공합니다.
      • InMemory Database: Entity Framework Core의 InMemory 데이터베이스는 테스트 목적으로 사용할 수 있습니다. 예를 들면, options.UseInMemoryDatabase("MyDb");와 같이 설정합니다. 이는 실제 데이터베이스 대신 메모리 내에서 데이터를 관리합니다.

이 구조를 통해, 모델 클래스는 'Models' 폴더에, DbContext 클래스는 'Data' 폴더에 명확하게 구분되어 있어 프로젝트의 구조가 더 명확하고 관리하기 쉬워집니다.

CAUTION

위 예시에서 사용된 하드 코딩된 데이터베이스 연결 문자열은 주로 학습이나 데모 목적으로 사용됩니다. 실제 현업 프로젝트에서는 보안, 유연성 및 확장성을 고려하여 연결 문자열을 다르게 관리하는 것이 좋습니다. 일반적으로, 연결 문자열은 구성 파일이나 환경 변수를 통해 관리되며, 이는 코드를 외부에서 변경할 수 있게 하고 민감한 정보를 보호하는 데 도움이 됩니다. 또한, 클라우드 기반 애플리케이션에서는 클라우드 서비스 제공업체의 관리 도구를 통해 연결 문자열을 설정하고 관리하는 것이 일반적입니다.

데이터베이스 만들기 및 관리

  1. 마이그레이션을 사용하여 데이터베이스 생성

    • 패키지 관리자 콘솔에서 Microsoft.EntityFrameworkCore.Tools를 설치합니다.
    • Add-Migration InitialCreate 명령을 실행하여 첫 번째 마이그레이션을 추가합니다. 이 과정은 모델 변경 사항을 데이터베이스 스키마로 변환하는 데 필요합니다.
    • Update-Database 명령을 실행하여 데이터베이스를 생성합니다. 이 명령은 마이그레이션을 데이터베이스에 적용하여 스키마를 최신 상태로 유지합니다.
  2. .NET Core CLI를 사용한 마이그레이션 및 데이터베이스 업데이트

    • .NET Core CLI를 사용하는 경우, 다음 명령으로 마이그레이션과 데이터베이스 업데이트를 진행할 수 있습니다:
      • 마이그레이션 추가: dotnet ef migrations add InitialCreate
      • 데이터베이스 업데이트: dotnet ef database update

    이 명령들은 각각 마이그레이션을 생성하고, 생성된 마이그레이션을 바탕으로 데이터베이스를 최신 상태로 업데이트하는 데 사용됩니다.

  3. 여러 DbContext 클래스 관리

    • 프로젝트에 여러 DbContext 클래스가 있는 경우, 각 DbContext에 대해 별도의 마이그레이션을 생성하고 관리해야 합니다.
    • 마이그레이션을 추가할 때, -Context 옵션을 사용하여 특정 DbContext를 지정합니다. 예: Add-Migration InitialCreate -Context MyDbContext
    • 데이터베이스를 업데이트할 때도 -Context 옵션을 사용하여 대상 DbContext를 지정합니다. 예: Update-Database -Context MyDbContext
  4. 마이그레이션 파일 위치 지정

    • 마이그레이션 파일의 위치를 지정하고 싶은 경우, Add-Migration 명령에 -OutputDir 옵션을 사용합니다.
    • 예를 들어, 마이그레이션 파일을 Data/Migrations 폴더에 생성하고 싶다면, 명령은 다음과 같이 됩니다: Add-Migration InitialCreate -OutputDir Data/Migrations
    • 이 옵션을 사용하면 지정된 폴더 내에 마이그레이션 파일이 생성되며, 프로젝트 구조를 더 체계적으로 관리할 수 있습니다.

CRUD 코드 조각

코드 조각 1: State 데이터 입력

EF Core를 사용하여 State 엔터티에 새 데이터를 추가하는 방법입니다.

using HawasoTribe.Data;
using HawasoTribe.Models;

// 데이터베이스 컨텍스트 인스턴스 생성
using var context = new TribeDbContext();

// 새 State 인스턴스 생성
var newState = new State { Name = "California" };

// State 추가
context.States.Add(newState);

// 변경사항 저장
context.SaveChanges();
  • State 인스턴스를 생성하고 이름을 설정합니다.
  • Add 메서드를 사용하여 State를 컨텍스트에 추가합니다.
  • SaveChanges 메서드를 호출하여 변경사항을 데이터베이스에 반영합니다.

코드 조각 2: State 데이터 조회

EF Core를 사용하여 State 엔터티의 데이터를 조회하는 방법입니다.

using HawasoTribe.Data;
using System.Linq;

// 데이터베이스 컨텍스트 인스턴스 생성
using var context = new TribeDbContext();

// 모든 State 데이터 조회
var states = context.States.ToList();

// 조회된 데이터 출력
foreach (var state in states)
{
    Console.WriteLine($"State ID: {state.StateId}, Name: {state.Name}");
}
  • ToList 메서드를 사용하여 모든 State 데이터를 조회합니다.
  • 조회된 데이터를 반복문을 통해 출력합니다.

코드 조각 3: State 데이터 수정

EF Core를 사용하여 State 엔터티의 데이터를 수정하는 방법입니다.

using HawasoTribe.Data;
using System.Linq;

// 데이터베이스 컨텍스트 인스턴스 생성
using var context = new TribeDbContext();

// 수정할 State 데이터 조회
var state = context.States.FirstOrDefault(s => s.Name == "California");

// 데이터가 존재하는 경우, 이름 수정
if (state != null)
{
    state.Name = "New California";
    context.SaveChanges();
}
  • FirstOrDefault 메서드를 사용하여 특정 조건에 맞는 State 데이터를 조회합니다.
  • 조회된 데이터의 속성을 수정하고 SaveChanges를 호출하여 데이터베이스에 반영합니다.

코드 조각 4: State 데이터 삭제

EF Core를 사용하여 State 엔터티의 데이터를 삭제하는 방법입니다.

using HawasoTribe.Data;


using System.Linq;

// 데이터베이스 컨텍스트 인스턴스 생성
using var context = new TribeDbContext();

// 삭제할 State 데이터 조회
var stateToDelete = context.States.FirstOrDefault(s => s.Name == "New California");

// 데이터가 존재하는 경우, 삭제
if (stateToDelete != null)
{
    context.States.Remove(stateToDelete);
    context.SaveChanges();
}
  • FirstOrDefault를 사용하여 삭제할 State 데이터를 조회합니다.
  • 조회된 데이터가 존재할 경우, Remove 메서드를 사용하여 데이터를 삭제합니다.
  • SaveChanges를 호출하여 삭제를 데이터베이스에 반영합니다.

코드 조각 5: Update 메서드 사용

EF Core에서 Update 메서드를 사용하여 State 엔터티의 데이터를 수정하는 방법입니다.

using HawasoTribe.Data;
using HawasoTribe.Models;

// 데이터베이스 컨텍스트 인스턴스 생성
using var context = new TribeDbContext();

// 수정할 State 개체 생성
var updatedState = new State { StateId = 1, Name = "Updated California" };

// State 수정
context.States.Update(updatedState);

// 변경사항 저장
context.SaveChanges();
  • 기존의 State 엔터티를 데이터베이스에서 가져오지 않고, 새로운 인스턴스를 생성합니다.
  • 수정할 StateStateId와 변경하고자 하는 속성을 설정합니다.
  • Update 메서드를 사용하여 컨텍스트에 State를 추가합니다. 이 메서드는 모든 필드에 대한 업데이트 쿼리를 생성합니다.
  • SaveChanges 메서드를 호출하여 변경사항을 데이터베이스에 반영합니다.
  • Update 메서드는 데이터베이스에서 엔터티를 직접 조회하지 않고, 엔터티의 전체 상태를 Modified로 설정하여 업데이트합니다.
  • 이 방법은 특히 이미 인스턴스화된 개체에 대해 전체 필드 업데이트를 수행할 때 유용합니다.
  • Update 메서드 사용 시 주의할 점은, 수정되지 않은 필드까지 포함하여 모든 필드에 대해 업데이트 쿼리가 실행될 수 있다는 것입니다. 이로 인해 성능상의 고려가 필요할 수 있습니다.
  • 데이터베이스에 StateId가 1인 State 엔터티가 없는 경우, Update 메서드는 아무런 변경도 발생시키지 않으며, 엔터티의 존재 여부를 먼저 확인하는 추가적인 로직이 필요합니다.

코드 조각 6: Tribe 데이터 입력 및 State 이름 조회

EF Core를 사용하여 Tribe 엔터티에 샘플 데이터를 추가하고, Include 메서드를 사용하여 관련 State 이름과 함께 데이터를 조회하는 방법입니다.

using HawasoTribe.Data;
using HawasoTribe.Models;
using Microsoft.EntityFrameworkCore;
using System.Linq;

// 데이터베이스 컨텍스트 인스턴스 생성
using var context = new TribeDbContext();

// 샘플 State 데이터 입력
var california = new State { Name = "California" };
context.States.Add(california);
context.SaveChanges();

// 샘플 Tribe 데이터 입력
var tribe1 = new Tribe { Name = "Tribe 1", State = california };
context.Tribes.Add(tribe1);
context.SaveChanges();

// Tribe 데이터와 관련 State 이름 조회
var tribesWithStates = context.Tribes
    .Include(t => t.State)
    .ToList();

// 조회된 데이터 출력
foreach (var tribe in tribesWithStates)
{
    Console.WriteLine($"Tribe ID: {tribe.TribeId}, Name: {tribe.Name}, State: {tribe.State.Name}");
}
  • StateTribe 인스턴스를 생성하고, Add 메서드를 사용하여 컨텍스트에 추가합니다.
  • SaveChanges 메서드를 호출하여 샘플 데이터를 데이터베이스에 반영합니다.
  • Tribe 데이터를 조회할 때 Include 메서드를 사용하여 연관된 State 엔터티의 데이터도 함께 로드합니다. 이는 EF Core의 즉시 로딩(Eager Loading) 방식입니다.
  • 조회된 Tribe 데이터와 함께 각 Tribe가 속한 State의 이름도 출력합니다.

이 코드 조각에서는 EF Core의 Include 메서드를 사용하여 연관된 엔터티를 함께 조회하는 방법을 보여줍니다. 이 방식은 관계형 데이터베이스에서 연관된 데이터를 함께 로드할 때 유용하며, 데이터의 관계를 효과적으로 관리할 수 있게 해줍니다.

EF Core의 Include 메서드는 SQL의 조인과 유사한 개념으로, 관련된 엔터티를 주 엔터티와 함께 로드하여 쿼리 결과에 포함시키는 기능을 제공합니다.

CRUD 작업 단계별 실행

Program.cs 파일에서 아래 단계별로 코드를 작성하고, Visual Studio의 "디버그 > 디버깅하지 않고 시작"을 선택하거나, .NET Core CLI에서 dotnet run 명령을 사용하여 프로그램을 실행하세요.

  1. 데이터 생성

    • Program.cs 파일에 데이터를 생성하는 코드를 추가합니다.
    • 여러 주(State)를 추가하고 저장합니다.
    using System;
    using var context = new TribeDbContext();
    
    Console.WriteLine("새로운 주 추가");
    context.Add(new State { Name = "샘플 주" }); // 일반 Add 메서드 사용
    context.States.Add(new State { Name = "또 다른 주" }); // DbSet의 Add 메서드 사용
    context.SaveChanges();
    
    • 첫 번째 State 개체는 context.Add()를 사용하여 추가되며, 이는 DbContext의 일반적인 Add 메서드입니다.
    • 두 번째 State 개체는 context.States.Add()를 사용하여 추가되며, 이는 States DbSet에 직접 추가하는 방법입니다.
    • 실행 후, SQL Server Management Studio 또는 다른 데이터베이스 관리 툴을 사용하여 LocalDB에 데이터가 정상적으로 추가되었는지 확인합니다.

    미국의 주들을 추가하는 예시:

    context.Add(new State { Name = "California" });
    context.Add(new State { Name = "New York" });
    context.Add(new State { Name = "Texas" });
    context.Add(new State { Name = "Florida" });
    context.Add(new State { Name = "Illinois" });
    
  2. 데이터 조회

    • 추가된 데이터를 조회하는 코드를 작성합니다.
    Console.WriteLine("주 조회");
    var states = context.States.ToList();
    foreach (var state in states)
    {
        Console.WriteLine($"State ID: {state.StateId}, Name: {state.Name}");
    }
    
  3. **데이터 업데이트 및 조회

    • 특정 주(State)의 이름을 업데이트하고, 새로운 부족(Tribe)을 추가한 후 데이터를 조회합니다.
    Console.WriteLine("주 업데이트 및 부족 추가");
    var firstState = context.States.First();
    firstState.Name = "업데이트된 주";
    firstState.Tribes.Add(new Tribe { Name = "새로운 부족" });
    context.SaveChanges();
    
    // 업데이트된 데이터 조회
    var updatedState = context.States.Include(s => s.Tribes).First(s => s.StateId == firstState.StateId);
    Console.WriteLine($"Updated State: {updatedState.Name}, Tribes: {string.Join(", ", updatedState.Tribes.Select(t => t.Name))}");
    
  4. 데이터 삭제 및 조회

    • 특정 주(State)를 삭제하고 남은 데이터를 조회합니다.
    Console.WriteLine("주 삭제");
    var stateToDelete = context.States.First();
    context.States.Remove(stateToDelete);
    context.SaveChanges();
    
    // 삭제 후 남은 데이터 조회
    var remainingStates = context.States.ToList();
    foreach (var state in remainingStates)
    {
        Console.WriteLine($"State ID: {state.StateId}, Name: {state.Name}");
    }
    
    • 최종적으로, TribeState를 참조하여 데이터를 추가합니다.
    Console.WriteLine("새 부족 및 주 참조 추가");
    var newState = new State { Name = "새로운 참조 주" };
    var newTribe = new Tribe { Name = "참조된 부족", State = newState };
    context.Tribes.Add(newTribe);
    context.SaveChanges();
    
    • 이 코드를 실행한 후, 데이터베이스에서 StateTribe가 정상적으로 연결되어 있는지 확인합니다.

강의에서 처음 연습한 전체 소스 코드는 다음과 같습니다.

using HawasoTribe.Data;
using HawasoTribe.Models;

using var context = new TribeDbContext();

context.Database.EnsureDeleted();
context.Database.EnsureCreated();

Console.WriteLine("새로운 주 추가");
context.Add(new State { Name = "New Jersey" });
context.States.Add(new State { Name = "New York" });
context.SaveChanges();

Console.WriteLine("주 목록");
var states = context.States.ToList();
foreach (var state in states)
{
    Console.WriteLine($"{state.StateId}: {state.Name}");
}

// 첫 번째 주만 읽어와서 이름을 SA로 변경합니다.
Console.WriteLine("주 업데이트");
var firstState = context.States.FirstOrDefault();
if (firstState != null)
{
    firstState.Name = "SA";
    context.SaveChanges();
}

// 첫 번째 주만 삭제
Console.WriteLine("첫 번째 주만 삭제");
var firstState2 = context.States.FirstOrDefault();
if (firstState2 != null)
{
    context.States.Remove(firstState2);
    context.SaveChanges();
}

Console.WriteLine("주 목록");
var states2 = context.States.ToList();
foreach (var state in states2)
{
    Console.WriteLine($"{state.StateId}: {state.Name}");
}

이렇게 구성된 CRUD 작업은 기본적인 데이터베이스 작업을 실습하는 데 도움이 됩니다. 각 단계별로 코드를 실행하여 결과를 확인하면서 Entity Framework Core의 기능을 체험할 수 있습니다.

CRUD 실습

1. 데이터 생성 (Create)

using HawasoTribe.Data;
using HawasoTribe.Models;
using System;
using System.Linq;
using Microsoft.EntityFrameworkCore;

// 1-1. 데이터베이스 초기화
using var context = new TribeDbContext();
context.Database.EnsureDeleted();
context.Database.EnsureCreated();

// 1-2. 새 State와 Tribe 추가
Console.WriteLine("새 State와 Tribe 추가");
var state1 = new State { Name = "California" };
state1.Tribes.AddRange(new[]
{
    new Tribe { Name = "Tribe A" },
    new Tribe { Name = "Tribe B" }
});

var state2 = new State { Name = "Texas" };
state2.Tribes.Add(new Tribe { Name = "Tribe C" });

context.States.AddRange(state1, state2);
context.SaveChanges();

2. 데이터 조회 (Read)

// 2-1. State 목록 조회
Console.WriteLine("\nState 목록:");
var states = context.States.ToList();
foreach (var state in states)
{
    Console.WriteLine($"State ID: {state.StateId}, Name: {state.Name}");
}

3. 데이터 업데이트 (Update)

// 3-1. State 이름 업데이트
Console.WriteLine("\nState 이름 업데이트");
var firstState = context.States.First();
firstState.Name = "Updated California";
context.SaveChanges();

// 3-2. 업데이트된 데이터 조회
Console.WriteLine($"\nUpdated State: {firstState.Name}");

4. 데이터 삭제 (Delete)

// 4-1. 특정 State 삭제
Console.WriteLine("\n특정 State 삭제");
var stateToDelete = context.States.LastOrDefault();
if (stateToDelete != null)
{
    context.States.Remove(stateToDelete);
    context.SaveChanges();
}

// 4-2. 삭제 후 데이터 조회
Console.WriteLine("\n남은 State 목록:");
var remainingStates = context.States.ToList();
foreach (var state in remainingStates)
{
    Console.WriteLine($"State ID: {state.StateId}, Name: {state.Name}");
}

5. 부족(Tribe) 추가 및 조회

// 5-1. 새로운 Tribe 추가 및 조회
Console.WriteLine("\n새로운 Tribe 추가 및 조회");
var newState = new State { Name = "New State" };
var newTribe = new Tribe { Name = "New Tribe", State = newState };
context.Tribes.Add(newTribe);
context.SaveChanges();

var tribes = context.Tribes.Include(t => t.State).ToList();
foreach (var tribe in tribes)
{
    Console.WriteLine($"Tribe ID: {tribe.TribeId}, Name: {tribe.Name}, State: {tribe.State.Name}");
}

데이터 업데이트

EF Core에서의 데이터 업데이트

Entity Framework Core (EF Core)에서 데이터를 업데이트하는 주요 방법은 두 가지입니다:

  1. 상태 추적을 통한 자동 업데이트
  2. Update 메서드 사용

1. 상태 추적을 통한 자동 업데이트

EF Core는 DbContext를 통해 가져온 Tribe 엔터티의 상태를 추적합니다. 이 방법은 다음과 같은 단계를 포함합니다:

  • 데이터베이스에서 Tribe 엔터티를 조회합니다.
  • 엔터티의 속성을 변경합니다.
  • SaveChanges 또는 SaveChangesAsync 메서드를 호출합니다.

예시:

var tribe = context.Tribes.First(t => t.TribeId == tribeId);
tribe.Name = "새로운 부족 이름";
context.SaveChanges();

이 경우, EF Core는 tribe 개체의 상태가 변경되었음을 감지하고, SaveChanges 호출 시 해당 변경사항을 데이터베이스에 반영합니다.

2. Update 메서드 사용

Update 메서드는 DbContext에서 제공하는 다른 방법으로, 특히 데이터베이스에서 직접 개체를 조회하지 않고 업데이트를 수행할 때 유용합니다. 이 메서드는 엔터티의 상태를 Modified로 설정합니다.

예시:

var tribe = new Tribe { TribeId = tribeId, Name = "새로운 부족 이름" };
context.Tribes.Update(tribe);
context.SaveChanges();

이 경우, EF Core는 tribe 개체 전체가 변경되었다고 간주하고, 모든 필드에 대해 업데이트 쿼리를 실행합니다.

결론

  • 상태 추적을 사용한 자동 업데이트는 데이터베이스에서 Tribe 엔터티를 직접 조회한 후 필요한 속성만 변경하는 경우에 적합합니다.
  • Update 메서드는 이미 인스턴스화된 Tribe 개체를 가지고 있고, 데이터베이스에서 해당 엔터티를 조회하지 않을 때 유용합니다.

사용 상황과 필요에 따라 적절한 업데이트 방식을 선택하는 것이 중요합니다.

마무리

본 문서를 끝까지 읽으셨다면, EF Core의 기초를 익히는 데 있어 이 내용을 시간이 나실 때마다 여러 번 실습해 보시는 것을 추천드립니다. 이를 통해 EF Core의 활용에 더욱 능숙해지시기를 바라며, 이 문서가 시작점으로서 여러분에게 큰 도움이 되었기를 기대합니다.

EF Core에 대해 좀 더 학습하고자 하는 분들은 다음 문서도 참고하세요.

Scaffold-DbContext로 데이터베이스 모델링

ASP.NET Core에서 EF Core 사용하기





















더 깊이 공부하고 싶다면
DevLec에서는 실무 중심의 C#, .NET, ASP.NET Core, Blazor, 데이터 액세스 강좌를 단계별로 제공합니다. 현재 수강 가능한 강좌 외에도 더 많은 과정이 준비되어 있습니다.
DevLec.com에서 자세한 커리큘럼을 확인해 보세요.
DevLec 공식 강의
C# Programming
C# 프로그래밍 입문
프로그래밍을 처음 시작하는 입문자를 위한 C# 기본기 완성 과정입니다.
ASP.NET Core 10.0
ASP.NET Core 10.0 시작하기 MVC Fundamentals Part 1 MVC Fundamentals Part 2
웹 애플리케이션의 구조와 MVC 패턴을 ASP.NET Core로 실습하며 익힐 수 있습니다.
Blazor Server
풀스택 웹개발자 과정 Part 1 풀스택 웹개발자 과정 Part 2 풀스택 웹개발자 과정 Part 3
실무에서 바로 활용 가능한 Blazor Server 기반 관리자·포털 프로젝트를 만들어 봅니다.
Data & APIs
Entity Framework Core 시작하기 ADO.NET Fundamentals Blazor Server Fundamentals Minimal APIs
데이터 액세스와 Web API를 함께 이해하면 실무 .NET 백엔드 개발에 큰 도움이 됩니다.
VisualAcademy Docs의 모든 콘텐츠, 이미지, 동영상의 저작권은 박용준에게 있습니다. 저작권법에 의해 보호를 받는 저작물이므로 무단 전재와 복제를 금합니다. 사이트의 콘텐츠를 복제하여 블로그, 웹사이트 등에 게시할 수 없습니다. 단, 링크와 SNS 공유, Youtube 동영상 공유는 허용합니다. www.VisualAcademy.com
박용준 강사의 모든 동영상 강의는 데브렉에서 독점으로 제공됩니다. www.devlec.com