소스 코드에서 SQL을 작성하는 것이 안티 패턴으로 간주됩니까?

다음과 같이 SQL을 응용 프로그램에 하드 코딩하는 안티 패턴으로 간주됩니까?

public List<int> getPersonIDs()
{    
    List<int> listPersonIDs = new List<int>();
    using (SqlConnection connection = new SqlConnection(
        ConfigurationManager.ConnectionStrings["Connection"].ConnectionString))
    using (SqlCommand command = new SqlCommand())
    {
        command.CommandText = "select id from Person";
        command.Connection = connection;
        connection.Open();
        SqlDataReader datareader = command.ExecuteReader();
        while (datareader.Read())
        {
            listPersonIDs.Add(Convert.ToInt32(datareader["ID"]));
        }
    }
    return listPersonIDs;
}

일반적으로 리포지토리 레이어 등이 있지만 위 코드에서 단순화하기 위해 제외했습니다.

최근에 SQL이 소스 코드로 작성되었다고 불평 한 동료로부터 피드백을 받았습니다. 나는 왜 그런지 물어볼 기회를 얻지 못했고, 그는 이제 2 주간 (아마도 더) 떨어져 있습니다. 나는 그가 다음 중 하나를 의미한다고 가정한다.

  1. LINQ
    또는
  2. SQL에 저장 프로 시저 사용

제가 맞습니까? 소스 코드에서 SQL을 작성하는 것이 안티 패턴으로 간주됩니까? 우리는이 프로젝트를 수행하는 작은 팀입니다. 저장 프로 시저의 이점 SQL 개발자가 개발 프로세스 (저장 프로 시저 작성 등)에 참여할 수 있다는 것입니다.

편집
하드 코딩 된 SQL 문에 대한 다음 링크 회담 : https://docs.microsoft.com/en-us/sql/odbc/reference/develop-app/hard-coded-sql-statements을 . SQL 문을 준비하면 어떤 이점이 있습니까?



답변

단순성을 위해 중요한 부분을 제외했습니다. 저장소는 지속성을위한 추상화 계층입니다. 지속성을 자체 계층으로 분리하여 필요할 때 지속성 기술을보다 쉽게 변경할있습니다 . 따라서, 지속성 계층 외부에 SQL을 갖는 것은 별도의 지속성 계층을 갖는 노력을 완전히 방해합니다.

결과 : SQL은 SQL 기술에 고유 한 지속성 계층 내에서 양호합니다 (예 : SQL은 a는 SQLCustomerRepository아니지만 괜찮음 MongoCustomerRepository). 퍼시스턴스 레이어 외부에서 SQL은 추상화를 중단하므로 (나에 의해) 매우 나쁜 습관으로 간주됩니다 .

LINQ 또는 JPQL과 같은 도구는 SQL의 특징을 추상화 할 수 있습니다. 저장소 외부에 LINQ-Code 또는 JPQL 쿼리가 있으면 원시 SQL과 마찬가지로 지속성 추상화가 중단됩니다.


별도 지속성 계층의 또 다른 장점은 DB 서버를 설정하지 않고도 비즈니스 로직 코드를 단위 테스트 할 수 있다는 것입니다.

언어가 지원하는 모든 플랫폼에서 재현 가능한 결과로 메모리 프로파일이 낮고 빠른 단위 테스트가 가능합니다.

MVC + Service 아키텍처에서 이는 저장소 인스턴스를 모의하고 메모리에 일부 모의 데이터를 작성하고 특정 게터가 호출 될 때 저장소가 해당 모의 데이터를 리턴하도록 정의하는 간단한 작업입니다. 그런 다음 단위 테스트 당 테스트 데이터를 정의하고 나중에 DB 정리에 대해 걱정하지 않아도됩니다.

DB에 대한 쓰기 테스트는 간단합니다. 지속성 계층에서 관련 업데이트 메소드가 호출되었는지 확인하고 해당 상황이 발생했을 때 엔티티가 올바른 상태인지 확인하십시오.


답변

오늘날 대부분의 표준 비즈니스 응용 프로그램은 서로 다른 책임을 가진 다른 계층을 사용합니다. 그러나 어떤 레이어는 사용 하여 응용 프로그램, 어느 계층 당신과 당신의 팀까지 인 책임이있다. 당신이 우리에게 보여준 함수에 SQL을 직접 배치하는 것이 옳은지 아닌지를 결정하기 전에 알아야 할 사항

  • 응용 프로그램의 어떤 계층에 어떤 책임이 있습니까?

  • 위의 기능은 어느 계층에서

이에 대한 “하나의 솔루션”은 없습니다. 일부 응용 프로그램에서 설계자는 ORM 프레임 워크를 사용하여 프레임 워크가 모든 SQL을 생성하도록합니다. 일부 응용 프로그램에서 설계자는 이러한 SQL을 저장 프로 시저에만 독점적으로 저장하는 것을 선호합니다. 일부 응용 프로그램의 경우 SQL이있는 수작업 지속성 (또는 리포지토리) 계층이 있으며, 다른 응용 프로그램의 경우 특정 환경에서 해당 지속성 계층에 SQL을 엄격하게 배치하여 예외를 정의하는 것이 좋습니다.

그래서 당신에 대해 생각할 필요가 무엇을 : 당신이 레이어를 원하는 또는 필요 특정 응용 프로그램에서, 그리고 어떻게 당신이 책임 원하는? “보통 리포지토리 계층을 갖고 싶습니다”라고 썼지 만, 그 계층 내에서 갖고 싶은 정확한 책임은 무엇이며, 다른 곳에서 어떤 책임을지고 싶습니까? 먼저 대답하면 스스로 질문에 대답 할 수 있습니다.


답변

Marstato가 좋은 대답을하지만 해설을 더 추가하고 싶습니다.

소스의 SQL은 안티 패턴이 아니지만 문제를 일으킬 수 있습니다. SQL 쿼리를 모든 폼에 드롭 된 구성 요소의 속성에 넣어야 할 때를 기억합니다. 이로 인해 상황이 정말 추악 해졌으며 쿼리를 찾기 위해 농구대를 뛰어 넘어야했습니다. 나는 작업하고있는 언어의 한계 내에서 가능한 한 데이터베이스 액세스를 중앙 집중화 할 것을 강력히 옹호했다 . 동료가이 어두운 날에 역화를 겪고있을 수 있습니다.

자, 일부 의견은 자동으로 나쁜 일처럼 벤더 잠금에 대해 이야기하고 있습니다. 그렇지 않습니다. 매년 Oracle을 사용하기 위해 6 개의 숫자 검사에 서명하는 경우 해당 데이터베이스에 액세스하는 응용 프로그램이 추가 Oracle 구문을 적절하게 사용하기를 원할 수 있습니다.그러나 최대로. 데이터베이스를 손상시키지 않는 SQL을 작성하는 “Oracle 방식”이있을 때 바닐라 ANSI SQL을 잘못 작성하는 코더가 반짝이는 데이터베이스를 손상시키는 경우에는 기쁘지 않습니다. 예, 데이터베이스를 변경하는 것이 더 어려울 수 있지만 20 년 동안 대규모 클라이언트 사이트에서 몇 번만 수행되었으며 DB2를 호스팅하는 메인 프레임이 더 이상 사용되지 않아 서비스가 중단되어 DB2-> Oracle에서 이러한 사례 중 하나가 이동하고 있음을 확인했습니다. . 그렇습니다. 벤더 잠금이지만 기업 고객에게는 Oracle 또는 Microsoft SQL Server와 같은 고가의 유능한 RDBMS를 지불 한 후 최대한 활용하는 것이 바람직합니다. 편안한 담요로 지원 계약이 있습니다. 풍부한 저장 프로 시저 구현을 사용하여 데이터베이스에 비용을 지불하는 경우

이것은 SQL 데이터베이스에 액세스하는 응용 프로그램을 작성하는 경우 다른 언어뿐만 아니라 SQL 도 배우고 쿼리 최적화도 의미합니다. 독창적으로 매개 변수가 지정된 쿼리를 사용할 수 있었을 때 거의 동일한 쿼리를 사용하여 SQL 캐시를 플러시하는 SQL 생성 코드를 작성하면 화가 날 것입니다.

변명도없고, 최대 절전 모드 벽 뒤에 숨어 있지 않습니다. 잘못 사용 된 ORM은 실제로 응용 프로그램의 성능을 저하 시킬 수 있습니다 . 몇 년 전에 Stack Overflow에 대한 질문을 본 기억이 있습니다.

최대 절전 모드에서 250,000 개의 레코드를 반복하여 몇 가지 속성 값을 확인하고 특정 조건과 일치하는 개체를 업데이트합니다. 속도가 조금 느립니다. 속도를 높이려면 어떻게해야합니까?

“업데이트 테이블 SET field1 = 여기서 field2는 True이고 Field3> 100″은 어떻습니까? 250,000 개의 객체를 생성하고 처리하는 것이 문제 일 수 있습니다.

즉, 사용하기에 적합하지 않은 경우에는 최대 절전 모드를 무시하십시오. 데이터베이스를 이해하십시오.

따라서 요약하면 코드에 SQL을 포함시키는 것은 나쁜 습관이 될 수 있지만 SQL을 포함시키지 않으려는 경우 훨씬 더 나쁜 일이 발생할 수 있습니다.


답변

예, SQL 문자열을 응용 프로그램 코드로 하드 ​​코딩하는 것은 일반적으로 안티 패턴입니다.

생산 코드에서 이것을 보며 수년간 개발 한 공차를 따로 떼어 봅시다. 동일한 파일에서 다른 구문과 완전히 다른 언어를 혼합하는 것은 일반적으로 바람직한 개발 기술이 아닙니다. 이것은 여러 언어에 문맥 적 의미를 부여하도록 설계된 Razor와 같은 템플릿 언어와 다릅니다. Sava B.가 아래 주석에서 언급 했듯이 C # 또는 다른 응용 프로그램 언어 (Python, C ++ 등)의 SQL은 다른 문자열이므로 의미 적으로 의미가 없습니다. 대부분의 경우 하나 이상의 언어를 혼합 할 때도 동일하게 적용되지만 C의 인라인 어셈블리, HTML에서 CSS의 작고 이해하기 쉬운 스 니펫 (CSS는 HTML과 혼합되도록 설계되어 있음)과 같이 수용 가능한 상황이 있습니다. ), 다른 사람.

클린 코드 : Robert C. Martin, pg.  288
(로버트 C. Martin은 언어 혼합, Clean Code , 17 장, “코드 냄새 및 휴리스틱 스”, 288 페이지)

이 응답을 위해 SQL에 초점을 맞출 것입니다 (질문에서 요청한대로). SQL을 일관된 분리 된 문자열 집합으로 저장할 때 다음과 같은 문제가 발생할 수 있습니다.

  • 데이터베이스 논리를 찾기가 어렵습니다. 모든 SQL 문을 찾기 위해 무엇을 검색합니까? “SELECT”, “UPDATE”, “MERGE”등이있는 문자열?
  • 동일하거나 유사한 SQL의 리팩토링 사용이 어려워집니다.
  • 다른 데이터베이스에 대한 지원을 추가하는 것은 어렵습니다. 어떻게 이것을 달성 할 수 있습니까? 각 데이터베이스에 대해 if..then 문을 추가하고 모든 쿼리를 메소드에 문자열로 저장합니까?
  • 개발자는 다른 언어로 된 문장을 읽고 메소드의 목적에서 메소드의 구현 세부 사항 (데이터 검색 방법 및 위치)으로 초점이 이동함에 따라주의가 산만 해집니다.
  • 한 줄짜리 문제는 그다지 큰 문제가되지 않지만 명령문이 더욱 복잡해지면 인라인 SQL 문자열이 분리되기 시작합니다. 113 라인으로 무엇을합니까? 방법에 113 줄을 모두 넣습니까?
  • 개발자는 SQL 편집기 (SSMS, SQL Developer 등)와 소스 코드간에 쿼리를 어떻게 효율적으로 앞뒤로 이동합니까? C #의 @접두사가 이것을 쉽게 만들어 주지만 각 SQL 줄을 인용하고 줄 바꿈을 피하는 많은 코드를 보았습니다.
    "SELECT col1, col2...colN"\
    "FROM painfulExample"\
    "WHERE maintainability IS NULL"\
    "AND modification.effort > @necessary"\
  • SQL을 주변 애플리케이션 코드와 정렬하는 데 사용되는 들여 쓰기 문자는 각 실행마다 네트워크를 통해 전송됩니다. 이것은 소규모 응용 프로그램에는 중요하지 않지만 소프트웨어 사용이 증가함에 따라 더해질 수 있습니다.

전체 ORM (Entity Framework 또는 Hibernate와 같은 객체 관계형 매퍼)은 응용 프로그램 코드에서 임의로 페퍼 SQL을 제거 할 수 있습니다. SQL과 리소스 파일을 사용하는 것은 단지 예일뿐입니다. ORM, 헬퍼 클래스 등은 모두보다 깨끗한 코드의 목표를 달성하는 데 도움이 될 수 있습니다.

이전 답변에서 Kevin이 말했듯이 작은 프로젝트에서는 코드의 SQL을 사용할 수 있지만 큰 프로젝트는 작은 프로젝트로 시작하며 대부분의 팀이 되돌아 갈 수있는 가능성은 종종 코드 크기에 반비례합니다.

프로젝트에서 SQL을 유지하는 간단한 방법이 많이 있습니다. 내가 자주 사용하는 방법 중 하나는 각 SQL 문을 Visual Studio 리소스 파일 (일반적으로 “sql”)에 넣는 것입니다. 도구에 따라 텍스트 파일, JSON 문서 또는 기타 데이터 소스가 합리적 일 수 있습니다. 경우에 따라 SQL 문자열을 적용하기위한 별도의 클래스가 최선의 선택 일 수 있지만 위에서 설명한 일부 문제가있을 수 있습니다.

SQL 예 : 어느 것이 더 우아해 보이는가? :

using(DbConnection connection = Database.SystemConnection()) {
    var eyesoreSql = @"
    SELECT
        Viewable.ViewId,
        Viewable.HelpText,
        PageSize.Width,
        PageSize.Height,
        Layout.CSSClass,
        PaginationType.GroupingText
    FROM Viewable
    LEFT JOIN PageSize
        ON PageSize.Id = Viewable.PageSizeId
    LEFT JOIN Layout
        ON Layout.Id = Viewable.LayoutId
    LEFT JOIN Theme
        ON Theme.Id = Viewable.ThemeId
    LEFT JOIN PaginationType
        ON PaginationType.Id = Viewable.PaginationTypeId
    LEFT JOIN PaginationMenu
        ON PaginationMenu.Id = Viewable.PaginationMenuId
    WHERE Viewable.Id = @Id
    ";
    var results = connection.Query<int>(eyesoreSql, new { Id });
}

된다

using(DbConnection connection = Database.SystemConnection()) {
    var results = connection.Query<int>(sql.GetViewable, new { Id });
}

SQL은 항상 쉽게 찾을 수있는 파일 또는 그룹화 된 파일 세트에 있으며, 각각 파일의 사용법보다는 설명이 포함 된 설명 이름을 가지고 있으며 각각은 애플리케이션 코드의 흐름을 방해하지 않는 주석을위한 공간이 있습니다. :

리소스의 SQL

이 간단한 방법은 독방 쿼리를 실행합니다. 내 경험상, “외국어”의 사용이 더욱 정교 해짐에 따라 혜택이 확대됩니다.
리소스 파일을 사용하는 것은 단지 예일뿐입니다. 언어 (이 경우 SQL) 및 플랫폼에 따라 다른 방법이 더 적절할 수 있습니다.

이 방법과 다른 방법은 다음과 같은 방식으로 위 목록을 해결합니다.

  1. 데이터베이스 코드는 이미 중앙 집중식이기 때문에 쉽게 찾을 수 있습니다. 더 큰 프로젝트에서는 like-SQL을 별도의 파일 (예 🙂 폴더 아래에 별도의 파일로 그룹화하십시오 SQL.
  2. 두 번째, 세 번째 등의 데이터베이스 지원이 더 쉽습니다. 각 데이터베이스의 고유 한 명령문을 리턴하는 인터페이스 (또는 다른 언어 추상화)를 작성하십시오. 각 데이터베이스에 대한 return SqlResource.DoTheThing;구현은 다음 과 유사한 명령문에 지나지 않습니다. 사실, 이러한 구현은 리소스를 건너 뛰고 문자열에 SQL을 포함 할 수 있지만 위의 일부 (전부는 아님) 문제가 여전히 발생합니다.
  3. 리팩토링은 간단합니다. 동일한 리소스를 재사용하십시오. 몇 가지 형식 문을 사용하여 다른 DBMS 시스템에 대해 동일한 리소스 항목을 오랫동안 사용할 수도 있습니다. 나는 이것을 자주한다.
  4. 2 차 언어를 사용하면 예를 들어 더 난해한 것이 아닌 설명적인 이름을 사용할 수 있습니다.sql.GetOrdersForAccountSELECT ... FROM ... WHERE...
  5. SQL 문은 크기와 복잡성에 관계없이 한 줄로 소환됩니다.
  6. SSMS 및 SQL Developer와 같은 데이터베이스 도구간에 수정이나 신중한 복사없이 SQL을 복사하여 붙여 넣을 수 있습니다. 따옴표가 없습니다. 후행 백 슬래시가 없습니다. 특히 Visual Studio 리소스 편집기의 경우 한 번의 클릭으로 SQL 문이 강조 표시됩니다. Ctrl + C를 누른 다음 SQL 편집기에 붙여 넣습니다.

리소스에서 SQL을 생성하는 것이 빠르므로 리소스 사용을 코드 내 SQL과 혼합 할 수있는 자극이 거의 없습니다.

선택한 방법에 관계없이 언어를 혼합하면 일반적으로 코드 품질이 저하됩니다. 여기에 설명 된 일부 문제와 솔루션이 개발자가 적절한 경우이 코드 냄새를 제거하는 데 도움이되기를 바랍니다.


답변

따라 다릅니다. 작동 할 수있는 여러 가지 접근 방식이 있습니다.

  1. SQL을 모듈화하고 SQL을 별도의 클래스, 함수 또는 패러다임이 사용하는 추상화 단위로 분리 한 다음 응용 프로그램 논리를 사용하여 호출하십시오.
  2. 복잡한 SQL을 모두보기로 이동 한 다음 응용 프로그램 논리에서 매우 간단한 SQL 만 수행하므로 모듈화 할 필요가 없습니다.
  3. 객체 관계형 매핑 라이브러리를 사용하십시오.
  4. YAGNI, 응용 프로그램 논리에 직접 SQL을 작성하십시오.

종종 그렇듯이 프로젝트에서 이미 이러한 기술 중 하나를 선택한 경우 나머지 프로젝트와 일관성이 있어야합니다.

(1)과 (3)은 데이터베이스를 다른 공급 업체로 교체하는 경우 응용 프로그램이 계속해서 기본 연기 테스트를 컴파일하고 통과한다는 의미에서 응용 프로그램 논리와 데이터베이스 간의 독립성을 유지하는 데 비교적 우수합니다. 그러나 대부분의 공급 업체는 SQL 표준을 완전히 준수하지 않으므로 공급 업체를 다른 공급 업체로 교체하려면 사용하는 기술에 관계없이 광범위한 테스트 및 버그 사냥이 필요할 수 있습니다. 나는 이것이 사람들이 생각하는 것만 큼 큰 일이라고 회의적이다. 데이터베이스 변경은 기본적으로 현재 데이터베이스를 필요에 맞게 얻을 수없는 경우 최후의 수단입니다. 이 경우 데이터베이스를 잘못 선택했을 수 있습니다.

(1)과 (3) 사이의 선택은 주로 ORM을 얼마나 좋아하는지의 문제입니다. 내 생각에 그들은 과용되었다. 행은 오브젝트가 ID를 갖는 방식으로 ID를 가지지 않기 때문에 관계형 데이터 모델을 잘 나타내지 않습니다. 고유 제약 조건, 조인과 관련하여 문제가 발생할 수 있으며 ORM의 힘에 따라 좀 더 복잡한 쿼리를 표현하는 데 어려움이있을 수 있습니다. 반면, (1) 아마도 ORM보다 훨씬 더 많은 코드가 필요할 것입니다.

(2) 내 경험으로는 거의 볼 수 없습니다. 문제는 많은 상점들이 SWE가 데이터베이스 스키마를 직접 수정하는 것을 금지한다는 것입니다 ( “DBA의 일이기 때문에”). 이것은 반드시 그 자체가 나쁜 것은 아닙니다. 스키마 변경은 문제를 일으킬 가능성이 크므로 신중하게 배포해야합니다. 그러나 (2)가 효과를 발휘하기 위해서는 SWE가 최소한 관료주의를 최소화하거나 전혀 갖지 않으면 서 새로운 견해를 도입하고 기존 견해의지지 질문을 수정할 수 있어야합니다. 귀하의 직장에서 그렇지 않은 경우, (2) 아마 효과가 없을 것입니다.

반면에 (2)가 작동하면 응용 프로그램 코드 대신 SQL에서 관계형 논리를 유지하기 때문에 대부분의 다른 솔루션보다 훨씬 낫습니다. 범용 프로그래밍 언어와 달리 SQL은 관계형 데이터 모델을 위해 특별히 설계되었으므로 복잡한 데이터 쿼리 및 변환을보다 잘 표현할 수 있습니다. 데이터베이스를 변경할 때 뷰를 나머지 스키마와 함께 이식 할 수도 있지만 이러한 이동은 더 복잡해집니다.

읽기의 경우 저장 프로시 저는 기본적으로 (2)의 crappier 버전입니다. 이 용량을 권장하지는 않지만 데이터베이스가 업데이트 가능한 뷰를 지원하지 않거나 한 번에 단일 행을 삽입하거나 업데이트하는 것보다 복잡한 작업을 수행 해야하는 경우 쓰기를 원할 수 있습니다 (예 : 트랜잭션, 읽기 및 쓰기 등). 트리거를 사용하여 저장 프로 시저를 뷰에 연결할 수 있습니다 (예 :CREATE TRIGGER trigger_name INSTEAD OF INSERT ON view_name FOR EACH ROW EXECUTE PROCEDURE procedure_name;)이지만 이것이 실제로 좋은 아이디어인지에 대한 의견은 상당히 다릅니다. 제안자는 응용 프로그램이 가능한 한 간단하게 실행하는 SQL을 유지한다고 알려줍니다. Detractors는 이것이 허용 할 수없는 수준의 “마법”이며 응용 프로그램에서 직접 프로 시저를 실행해야한다고 알려줍니다. 나는 당신의 저장 프로 시저가 보이는 나처럼 많은 역할을하는 경우이 더 좋은 생각이다라고 말하고 싶지만 INSERT, UPDATEDELETE, 그리고 나쁜 생각은 뭔가 다른 일을하는 경우. 궁극적으로 어떤 스타일이 더 적합한 지 스스로 결정해야합니다.

(4)는 해결책이 아닙니다. 소규모 프로젝트 또는 데이터베이스와 산발적으로 만 상호 작용하는 대규모 프로젝트에 유용합니다. 그러나 SQL이 많은 프로젝트의 경우 애플리케이션 주위에 동일한 쿼리가 중복되거나 유사하게 분산되어 가독성과 리팩토링을 방해 할 수 있으므로 좋지 않습니다.


답변

소스 코드에서 SQL을 작성하는 것이 안티 패턴으로 간주됩니까?

반드시 그런 것은 아닙니다. 여기에서 모든 주석을 읽으면 소스 코드에서 SQL 문을 하드 코딩하기위한 유효한 인수를 찾을 수 있습니다.

문을 어디에 두어야하는지 문제가 발생합니다 . 프로젝트 전체에 SQL 문을 배치하면 일반적으로 우리가 따르려고 노력하는 일부 SOLID 원칙을 무시하게 될 것입니다.

그가 의미한다고 가정; 어느 한 쪽:

1) LINQ 사용

또는

2) SQL에 대해 스토어드 프로 시저 사용

우리는 그가 무엇을 의미하는지 말할 수 없습니다. 그러나 우리는 추측 할 수 있습니다. 예를 들어, 가장 먼저 떠오르는 것은 벤더 잠금입니다 . SQL 문을 하드 코딩하면 응용 프로그램을 DB 엔진에 밀접하게 연결할 수 있습니다. 예를 들어, ANSI와 호환되지 않는 공급 업체의 특정 기능을 사용합니다.

이것은 반드시 잘못되거나 나쁘지는 않습니다. 나는 단지 사실을 가리키고 있습니다.

SOLID 원칙과 공급 업체 잠금을 무시하면 무시할 수있는 부정적인 결과가 발생할 수 있습니다. 그렇기 때문에 보통 팀과 함께 앉아 의심을 폭로하는 것이 좋습니다.

저장 프로 시저의 장점 SQL 개발자가 개발 프로세스 (저장 프로 시저 작성 등)에 참여할 수 있다는 이점이 있습니다.

저장 프로 시저의 장점과는 아무런 관련이 없다고 생각합니다. 또한 동료가 하드 코딩 된 SQL을 싫어하는 경우 비즈니스를 저장 프로 시저로 옮기면 그를 싫어할 것입니다.

편집 : 다음 링크는 하드 코딩 된 SQL 문에 대해 설명합니다 :  https://docs.microsoft.com/en-us/sql/odbc/reference/develop-app/hard-coded-sql-statements . SQL 문을 준비하면 어떤 이점이 있습니까?

예. 포스트는 준비된 진술 의 장점을 열거합니다 . 일종의 SQL 템플릿입니다. 문자열 연결보다 안전합니다. 그러나 게시물은 당신이 이런 식으로 가도록 격려하거나 당신이 옳다는 것을 확인하지 않습니다. 안전하고 효율적인 방식으로 하드 코딩 된 SQL을 사용하는 방법에 대해서만 설명합니다.

요약하면 먼저 동료에게 물어보십시오. 메일을 보내거나 전화를 겁니다. 그가 대답하든 말든 팀과 함께 앉아 의심을 폭로하십시오. 요구 사항에 가장 적합한 솔루션을 찾으십시오. 읽은 내용에 따라 잘못된 가정을하지 마십시오.


답변

나는 그것이 나쁜 습관이라고 생각합니다. 다른 사람들은 모든 데이터 액세스 코드를 자체 계층으로 유지하는 이점을 지적했습니다. 당신은 그것을 찾아 다닐 필요가 없으며, 최적화하고 테스트하기가 더 쉽습니다 … 그러나 그 계층 내에서도 ORM 사용, sprocs 사용 또는 SQL 쿼리를 문자열로 포함하는 몇 가지 선택이 있습니다. SQL 쿼리 문자열이 최악의 옵션이라고 말할 수 있습니다.

ORM을 사용하면 개발이 훨씬 쉬워지고 오류 발생 가능성이 줄어 듭니다. EF를 사용하면 모델 클래스를 작성하기 만하면 스키마를 정의 할 수 있습니다 (어쨌든 이러한 클래스를 작성해야했습니다). LINQ로 쿼리하는 것은 쉬운 일입니다. 종종 sproc을 작성하고 유지해야하는 2 줄의 c #을 사용하면됩니다. IMO는 생산성과 유지 보수성 측면에서 코드가 적고 문제가 적을 때 큰 이점이 있습니다. 그러나 수행중인 작업을 알고 있더라도 성능 오버 헤드가 있습니다.

Sproc (또는 함수)이 다른 옵션입니다. 여기서는 SQL 쿼리를 수동으로 작성합니다. 그러나 적어도 당신은 그들이 정확하다는 것을 확신합니다. .NET에서 작업하는 경우 SQL이 유효하지 않으면 Visual Studio에서 컴파일러 오류가 발생합니다. 대단하다. 일부 열을 변경하거나 제거하고 일부 쿼리가 유효하지 않은 경우 적어도 컴파일 시간 동안 열에 대해 찾을 가능성이 큽니다. 또한 자체 파일에서 sprocs를 유지 관리하는 것이 더 쉽습니다. 구문 강조, 자동 완성 등을 얻을 수 있습니다.

쿼리가 sproc로 저장된 경우 응용 프로그램을 다시 컴파일하고 다시 배포하지 않고도 쿼리를 변경할 수 있습니다. SQL의 무언가가 깨져 있음을 알게되면 DBA는 앱 코드에 액세스 할 필요없이 그것을 고칠 수 있습니다. 일반적으로 쿼리가 문자열 리터럴 인 경우 dbas는 거의 쉽게 작업을 수행 할 수 없습니다.

문자열 리터럴 인 SQL 쿼리는 데이터 액세스 C # 코드를 읽기 어렵게 만듭니다.

경험상 마법 상수는 좋지 않습니다. 여기에는 문자열 리터럴이 포함됩니다.