DEV/ETC

C# 에서 JPA 유사하게 사용하기

SBP 2025. 4. 24. 09:56

.NET EF Core를 이용한 데이터 조회 (JPA 비교)

네, Java의 JPA(Java Persistence API)와 매우 유사하게 .NET 환경에서도 ORM(Object-Relational Mapper) 기술인 Entity Framework Core (EF Core)를 사용하여 데이터베이스에 접속하고 데이터를 조회할 수 있습니다.

JPA와 EF Core 개념 비교

JPA 개념 .NET / EF Core 대응 개념 설명
@Entity, Mapping C# 클래스 모델, Conventions, Data Annotations, Fluent API Java 클래스를 DB 테이블에 매핑 <-> C# 클래스를 DB 테이블에 매핑
EntityManager DbContext (예: AppDbContext) 데이터베이스 연결 및 세션 관리, 엔티티 추적, 쿼리 및 저장 실행
persistence.xml DI 설정 (App.xaml.cs), appsettings.json, OnConfiguring 데이터베이스 연결 정보, ORM 설정 구성
JPQL, Criteria API LINQ (Language-Integrated Query), Raw SQL 객체 지향적인 방식으로 데이터를 쿼리 (가장 유사한 부분)
persist, merge Add, Update 메서드 객체를 DB에 저장하거나 수정
remove Remove 메서드 객체를 DB에서 삭제
commit, flush SaveChanges() / SaveChangesAsync() 변경 사항을 실제 데이터베이스에 반영

EF Core와 LINQ를 사용한 데이터 조회 예시

EF Core의 핵심은 DbContext 객체와 LINQ를 사용하여 데이터베이스와 상호작용하는 것입니다. LINQ를 사용하면 C# 코드 내에서 SQL과 유사한 방식으로 객체 지향적인 쿼리를 작성할 수 있습니다. EF Core는 이 LINQ 쿼리를 실제 DB SQL로 변환하여 실행합니다.

아래는 MsSqlDataService 또는 OracleDataService 와 같은 서비스 클래스 내에서 데이터를 조회하는 코드 예시입니다.

특정 이름으로 레코드 조회

JPA의 repository.findByName(name) 또는 JPQL의 "SELECT r FROM DatabaseRecord r WHERE r.Name = :name" 과 유사합니다.

// 예시: MsSqlDataService.cs 또는 OracleDataService.cs 내부

using Microsoft.EntityFrameworkCore; // ToListAsync, FirstOrDefaultAsync 등 사용
using System.Collections.Generic;
using System.Linq; // Where, Select 등 LINQ 메서드 사용
using System.Threading.Tasks;
using YourProjectName.DataAccess;
using YourProjectName.Models;
using YourProjectName.Services.Interfaces;

// ... (클래스 및 생성자) ...

public async Task<IEnumerable<DatabaseRecord>> GetRecordsByNameAsync(string name)
{
    try
    {
        // _context.DatabaseRecords 가 DB 테이블에 해당 (DbSet<DatabaseRecord>)
        // LINQ의 Where 메서드를 사용하여 조건 지정
        // ToListAsync()는 조건에 맞는 모든 결과를 비동기적으로 List<DatabaseRecord>로 가져옴
        var records = await _context.DatabaseRecords
                                    .Where(record => record.Name == name) // 조건절 (C# 람다식)
                                    .AsNoTracking() // 읽기 전용일 경우 추적 비활성화 (성능 향상)
                                    .ToListAsync(); // 결과 가져오기

        _logger.LogInformation("Found {Count} records with name '{Name}'.", records.Count, name);
        return records;
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Error getting records by name: {Name}", name);
        throw;
    }
}

ID로 단일 레코드 조회

JPA의 repository.findById(id) 또는 JPQL의 "SELECT r FROM DatabaseRecord r WHERE r.Id = :id" 와 유사합니다.

public async Task<DatabaseRecord?> GetSingleRecordByIdAsync(int id)
{
    try
    {
        // FirstOrDefaultAsync는 조건에 맞는 첫 번째 레코드를 찾거나 없으면 null 반환
        var record = await _context.DatabaseRecords
                                   .FirstOrDefaultAsync(record => record.Id == id);

        // FindAsync 도 PK 검색에 사용 가능: var record = await _context.DatabaseRecords.FindAsync(id);

        if (record != null)
        {
             _logger.LogInformation("Found record with ID: {RecordId}", id);
        }
        else
        {
             _logger.LogWarning("Record not found with ID: {RecordId}", id);
        }
        return record;
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Error getting record by ID: {RecordId}", id);
        throw;
    }
}

모든 레코드 조회

JPA의 repository.findAll() 또는 JPQL의 "SELECT r FROM DatabaseRecord r" 과 유사합니다.

public async Task<IEnumerable<DatabaseRecord>> GetAllRecordsAsync()
{
    try
    {
        return await _context.DatabaseRecords.AsNoTracking().ToListAsync();
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "Error getting all records.");
        throw;
    }
}

결론

현재 설정된 프로젝트 구조(EF Core, AppDbContext, 서비스 클래스)는 JPA와 매우 유사한 방식으로 데이터베이스 작업을 수행할 수 있도록 이미 준비되어 있습니다. DbContextLINQ를 사용하여 C# 코드 내에서 객체 지향적으로 데이터를 조회하고 조작할 수 있습니다.