Entity 프레임워크를 이용하여, Native 쿼리로 작동하는 방법을 사용해보자

레파지토리 패턴을 흉내내어 , Entity프레임워크에서 SQL 쿼리방식을 활용해보자

  • ORM은 팀문화상 사용못하거나, 복잡한 집계쿼리에서 ORM의 한계를 느낄때
  • 쿼리맵핑으로 성능에 중점을 둔 인기있는 서드파티툴인 Dapper 활용도 가능하지만, Entity의 Native Query 와 성능차이는 미비합니다. ( 쿼리자체 튜닝에 중점)
  • 일관성(only ORM or  only SQL) 유지 또는 하이브리드(ORM or NOT) 등 전략적 선택가능하며 Entity FrameWork는 공식 지원 라이브러리입니다.

Code Sample

//Entity
public class SomeLog
{
    [Key]
    public int no { get; set; }

    public string text { get; set; }

    public Datetime created_time { get; set; }
}

//Repository
public class LogRepository : DbContext
{
    private readonly AppSettings appSettings;

    public DbSet<SomeLog> someLogs { get; set; }

    public LogRepository(AppSettings _appSettings)
    {
        appSettings = _appSettings;
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (!optionsBuilder.IsConfigured)
        {
            string dbConnectionString = appSettings.DBConnectionLog;
            //사용DB변경가능,인프라
            optionsBuilder.UseNpgsql(dbConnectionString, o => o.SetPostgresVersion(8, 0));                
        }
    }
}

// Service
public class LogSummarySercice
{
    private ILogger _logger;
    private LogRepository _logRepository;

    public LogSummarySercice(ILogger<LogSummarySercice> logger,
        LogRepository logRepository)
    {
        _logger = logger;
        _logRepository = logRepository;
    }

    // SQL 버전
    public async Task<List<SomeLog>> findDailySummaryList(SearchFilter searchFilter)
    {
        var query ="select .....네이티브쿼리;"
        var result = _logRepository.someLogs
            .FromSqlRaw(query).ToList();

        return result;
    }

    // ORM 버전
    public async Task<List<SomeLog>> findDetailByFilter(SearchFilter searchFilter)
    {
        var item = _logRepository.someLogs.FirstOrDefault();
        return item;
    }
}


Key 제거

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder
                .Entity<QueryStringResult>(eb =>
                {
                    eb.HasNoKey();
                });
        }

ORM에서 Entity모델은 기본으로 Key가 정의되어야 하며 정의가 없을시 예외가 난다.

Native Query에서 반환되는 모델은 항상 Key를 가질필요는 없다. 이때 Key가 없는 모델을 만들고 싶으면 위와같이 키를 없애는 코드를 추가한다. 


주입방지

var password = new MySqlParameter("password", passWord);
var result = await Native.FromSqlRaw(@"SELECT to_base64(SHA2(@password,512)) AS result;", password).ToListAsync();

SQL문의 Param을 입력 인자로 받아서, 문자열로 합하게되면  보안 취약점이 생길수 있다.

입력 Param이 SQL문을 조작(sql injection) 할수 있기때문이며

SQL을 작성할 당시 보안에 유의하여 문자값을 만들수 있지만 개발자의 실수가 있을수 있는 부분이며

가장 안전한 방식은 SQL조작이 안되도록 SqlParameter객체를 생성하여 전달하는 방식이며 추천됩니다.


참고자료:







  • No labels