DbContext와 DbSet 기초
DbContext를 설정하고 엔터티를 정의하며 연결 문자열을 구성하고 첫 번째 쿼리를 실행합니다.
DbContext와 DbSet 기초은(는) CoddyKit의 무료 C# Academy 강의입니다. 이것은 4개 중 1번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 C# Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. C# Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
Entity Framework Core란 무엇인가요
EF Core는 공식 .NET 객체-관계형 매퍼입니다. C# 클래스(엔터티)를 데이터베이스 테이블에 매핑하고 LINQ를 사용하여 데이터를 조회하고 저장할 수 있으므로 대부분의 작업에서 SQL을 직접 작성할 필요가 없습니다.
엔터티 정의
엔터티는 속성이 데이터베이스 열에 매핑되는 단순한 C# 클래스입니다. 규칙에 따라 Id 또는 <TypeName>Id라는 이름의 속성이 기본 키가 됩니다.
public class Product
{
public int Id { get; set; }
public string Name { get; set; } = "";
public decimal Price { get; set; }
public int Stock { get; set; }
public DateTime CreatedAt { get; set; }
}DbContext 생성
DbContext는 데이터베이스에 접근하는 진입점입니다. 각 엔터티에 대한 DbSet<T> 속성을 보유하고 연결, 변경 추적 및 트랜잭션을 관리합니다.
using Microsoft.EntityFrameworkCore;
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options) { }
public DbSet<Product> Products => Set<Product>();
public DbSet<Order> Orders => Set<Order>();
}DbContext를 DI에 등록하기
AddDbContext를 Program.cs에서 호출하여 컨텍스트를 범위 지정 서비스로 등록하고 데이터베이스 공급자를 구성합니다.
builder.Services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(
builder.Configuration.GetConnectionString("Default")));
// For SQLite (great for development/testing):
// options.UseSqlite("Data Source=app.db");DbSet을 사용한 기본 쿼리
DbSet<T>은 LINQ 연산자를 제공합니다. 쿼리는 열거될 때까지(await ...ToListAsync()) 실행되지 않습니다. 이를 지연 실행이라고 합니다.
public class ProductService
{
private readonly AppDbContext _db;
public ProductService(AppDbContext db) => _db = db;
public async Task<List<Product>> GetExpensiveAsync(decimal minPrice)
{
return await _db.Products
.Where(p => p.Price >= minPrice)
.OrderBy(p => p.Name)
.ToListAsync();
}
}기본 키로 찾기
FindAsync는 데이터베이스에 접근하기 전에 로컬 변경 추적기 캐시를 먼저 확인합니다. 기본 키로 조회할 때 사용하면 불필요한 왕복을 피할 수 있습니다.
var product = await _db.Products.FindAsync(42);
if (product is null)
throw new KeyNotFoundException("Product not found");
// For complex keys, pass all key values:
var orderLine = await _db.OrderLines.FindAsync(orderId, productId);새 레코드 추가하기
Add를 호출하여 엔터티를 삽입 대기 상태로 만든 다음 SaveChangesAsync를 호출하여 커밋합니다. EF Core가 INSERT 문을 생성하고 자동으로 생성된 Id를 채웁니다.
var product = new Product
{
Name = "Mechanical Keyboard",
Price = 149.99m,
Stock = 50,
CreatedAt = DateTime.UtcNow
};
_db.Products.Add(product);
await _db.SaveChangesAsync();
Console.WriteLine(product.Id); // Auto-generated PK레코드 수정하기
EF Core가 로드한 엔터티는 추적됩니다. 속성을 직접 수정하고 SaveChangesAsync를 호출하면 EF Core가 변경 내용을 감지하여 최적화된 UPDATE 문을 생성합니다.
var product = await _db.Products.FindAsync(42);
if (product is not null)
{
product.Price = 129.99m;
product.Stock -= 1;
await _db.SaveChangesAsync(); // UPDATE Products SET Price=...
}레코드 삭제하기
Remove를 호출하여 엔터티를 삭제 대상으로 표시한 다음 SaveChangesAsync를 호출합니다. 엔터티를 로드하지 않고 대량 삭제를 수행하려면 ExecuteDeleteAsync(.NET 7 이상)를 사용합니다.
// Delete a tracked entity
_db.Products.Remove(product);
await _db.SaveChangesAsync();
// Bulk delete without loading (EF Core 7+)
await _db.Products
.Where(p => p.Stock == 0)
.ExecuteDeleteAsync();Fluent 방식으로 구성하기
OnModelCreating을 재정의하여 Fluent 방식으로 엔터티를 구성합니다. 테이블 이름, 열 형식, 제약 조건, 인덱스 및 관계를 설정할 수 있습니다.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>(entity =>
{
entity.ToTable("products");
entity.Property(p => p.Name).IsRequired().HasMaxLength(200);
entity.Property(p => p.Price).HasColumnType("decimal(18,2)");
entity.HasIndex(p => p.Name);
});
}실전: DbContext를 사용하는 리포지토리
일반적인 리포지토리는 DbContext를 감싸 데이터 접근 논리를 중앙화하고, 서비스 클래스에서 쿼리 세부 사항을 분리합니다.
public class ProductRepository : IProductRepository
{
private readonly AppDbContext _db;
public ProductRepository(AppDbContext db) => _db = db;
public async Task<Product?> GetByIdAsync(int id)
=> await _db.Products.AsNoTracking().FirstOrDefaultAsync(p => p.Id == id);
public async Task<List<Product>> SearchAsync(string query)
=> await _db.Products
.Where(p => p.Name.Contains(query))
.AsNoTracking()
.ToListAsync();
}빠른 확인
EF Core로 조회할 때 AsNoTracking()은 어떤 작업을 수행합니까?
복습: DbContext 및 DbSet 기본 사항
핵심 내용:
- DbContext는 데이터베이스와의 세션이며, DbSet<T>은 테이블을 나타냅니다
- DI에서
AddDbContext로 등록하며 기본적으로 범위 지정으로 설정됩니다 - LINQ 쿼리는 지연 실행되며
ToListAsync,FirstOrDefaultAsync로 실행합니다 - 변경 추적을 사용하면 SaveChangesAsync를 통해 UPDATE/DELETE를 자동으로 수행할 수 있습니다
- 읽기 전용 쿼리에는
AsNoTracking()을 사용하여 성능을 향상합니다
자주 묻는 질문
“DbContext와 DbSet 기초” 강의는 무료인가요?
네 — “DbContext와 DbSet 기초” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 C# Academy 강의 전체를 잠금 해제할 수 있습니다. C# Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“DbContext와 DbSet 기초”에서 뭘 배우나요?
DbContext를 설정하고 엔터티를 정의하며 연결 문자열을 구성하고 첫 번째 쿼리를 실행합니다. 브라우저에서 직접 실행하는 실습 코드로 C# Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
C# Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 C# Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 1번째 강의입니다.
“DbContext와 DbSet 기초” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 C# Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 C# Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- DbContext와 DbSet 기초
- 마이그레이션과 스키마 관리
- EF Core를 사용한 CRUD 작업
- 관계: 일대다와 다대다