본문 바로가기
Backend/C# .NET

Entity Framework Core 개념 / 장단점 / 코드 예제 / 사용 방법 / 데이터 가져오기, 수정, 삭제 / 샘플 코드

by SOLYI 2023. 11. 26.

EF Core?

EF Core는 Entity Framework의 경량화된 버전으로, .NET Core 및 .NET 5 이상에서 사용할 수 있다. 데이터베이스와의 상호 작용을 단순화하고 개발자가 데이터베이스에 대한 쿼리 및 조작을 수행할 수 있는 ORM(Object-Relational Mapping) 도구이다.

주요 기능

  • 데이터베이스에 대한 CRUD(Create, Read, Update, Delete) 작업을 지원한다.
  • LINQ(Language Integrated Query)를 사용하여 데이터베이스 쿼리를 작성할 수 있다.
  • 데이터베이스 스키마를 코드로 정의할 수 있는 Code First 접근 방식을 제공한다.
  • 다양한 데이터베이스 시스템과 호환된다.

EF Core의 장점

  • 개발자가 데이터베이스와의 상호 작용을 쉽게 할 수 있다.
  • 데이터베이스에 대한 추상화 계층을 제공하여 유지 보수 및 확장성을 향상시킨다.
  • 다양한 데이터베이스 시스템과의 호환성을 제공한다.
  • LINQ를 사용하여 간편하게 데이터베이스 쿼리를 작성할 수 있다.

EF Core의 한계

  • EF Core는 아직 모든 Entity Framework의 기능을 지원하지 않을 수 있다.
  • 일부 고급 데이터베이스 기능에 대한 지원이 제한적일 수 있다.
  • 성능 측면에서 일부 상황에서는 원시 SQL 쿼리를 작성하는 것이 더 효율적일 수 있다.

EF Core 사용 방법

  1. 프로젝트에 EF Core NuGet 패키지를 추가한다.
  2. DbContext 클래스를 작성하고 데이터베이스 연결 정보를 설정한다.
  3. 모델 클래스를 작성하고 데이터베이스 테이블과 매핑한다.
  4. LINQ를 사용하여 데이터베이스 쿼리를 작성하고 실행한다.
  5. 변경 내용을 데이터베이스에 저장하거나 업데이트한다.

Entity Framework Core 사용을 위한 데이터베이스 설치

  • SQL Server 설치
  • dotnet add package Microsoft.EntityFrameworkCore.SqlServer
  • 테스트를 위한 InMemory 설치
  • dotnet add package Microsoft.EntityFrameworkCore.InMemory

DbContext 서브 클래스 작성

public class CatalogContext : DbContext
{
    public CatalogContext(DbContextOptions<CatalogContext> options) : base(options)
    {
    }
    public DbSet<CatalogItem> CatalogItems { get; set; }
    public DbSet<CatalogBrand> CatalogBrands { get; set; }
    public DbSet<CatalogType> CatalogTypes { get; set; }
}

EF Core 구성 (데이터베이스 연결 정보 설정)

  • SQL Server 사용시
      builder.Services.AddDbContext<CatalogContext>(
          options => options.UseSqlServer(
              builder.Configuration.GetConnectionString("DefaultConnection")));
  • InMemory 사용시
      builder.Services.AddDbContext<CatalogContext>(options =>
          options.UseInMemoryDatabase());

데이터 가져오기

var brandItems = await _context.CatalogBrands
    .Where(b => b.Enabled)
    .OrderBy(b => b.Name)
    .Select(b => new SelectListItem {
        Value = b.Id, Text = b.Name })
    .ToListAsync();
  • 이름순 정렬, Enabled 속성으로 필터링, SelectListItem형식의 CatalogBrands를 조회
  • 즉각 실행하기 위해 .ToListAsync()를 호출을 추가하는 것이 중요하다.

데이터 저장

// 데이터 추가 Create
var newBrand = new CatalogBrand() { Brand = "Acme" };
_context.Add(newBrand);
await _context.SaveChangesAsync();

// 데이터 수정 read and update
var existingBrand = _context.CatalogBrands.Find(1);
existingBrand.Brand = "Updated Brand";
await _context.SaveChangesAsync();

// 데이터 삭제 read and delete (alternate Find syntax)
var brandToDelete = _context.Find<CatalogBrand>(2);
_context.CatalogBrands.Remove(brandToDelete);
await _context.SaveChangesAsync();
  • EF Core느 엔터티를 가져오고 저장하기 위한 동기/비동기 메서드를 모두 지원한다.
  • 웹 어플리케이션에서 데이터 액세스 작업을 기다리는 동안 웹서버 스레드가 차단되지 않도록 하깅 위해 비동기 메서드에 async/await 패턴을 사용하는 것이 좋다.

관련 데이터 가져오기

  • EF Core는 엔터티를 가져올 때 데이터베이스에 직접 저장되어있는 모든 프로퍼티를 함께 가져온다.
  • 관련 엔터티 목록들과 같은 Navigation 속성은 null 값으로 입력되는 경우가 있다.
  • 이 프로세스는 EF Core가 데이터를 필요 이상으로 가져오지 않게하므로, 요청을 신속하고 효율적인 방식으로 처리하고 응답을 반환해야하는 웹 어플리케이션에선 매우 중요하다.
  • 즉시 로드eager loading을 사용하여 엔터티와의 관계를 포함하려면 다음과 같이 쿼리에 Include 메서드를 사용하여 속성을 지정할 수 있다.
// .Include 를 사용하려면 using Microsoft.EntityFrameworkCore  을 추가해야한다.
var brandsWithItems = await _context.CatalogBrands
    .Include(b => b.Items)
    .ToListAsync();
  • 여러 관계를 포함할 수 있고, ThenInclude를 사용하여 하위 관계를 포함할 수도 있다.
  • 마침표로 구분된 문자열을 .Include() 메서드에 전달해서 Navigation 속성을 추가하는 방법도 있다.
  • .Include("Items.Products")
  • specification은 필터링 논리를 캡슐화할 수 있을 뿐만 아니라 어떤 프로퍼티를 읽어올지를 포함해 반환 데이터의 형태를 지정할 수 있다.
  • // 모든 표현식 기반 Include query = specification.Includes.Aggregate(query, (current, include) => current.Include(include)); // 문자열 기반 Include query = specification.IncludeStrings.Aggregate(query, (current, include) => current.Include(include));
  • 또 다른 방법으로는 명시적 로드explict loading이 있다. 이미 읽어온 엔터티에 추가 데이터를 가져올 수 있지만, DB 왕복 횟수를 최소화해야하는 웹 어플리케이션에서는 사용하지 않는 것이 좋다.
  • 기본적으로 사용하지 않도록 설정되어 있으며 Microsoft.EntityFrameworkCore.Proxies를 설치해야한다.
반응형