C #에서 MS SQL Server의 데이터를 쿼리하는 가장 좋은 방법은 무엇입니까?


9

C #의 MS SQL Server에서 데이터를 쿼리하는 가장 좋은 방법은 무엇입니까?

코드에 SQL 쿼리를 사용하는 것은 좋지 않습니다.

저장 프로 시저를 만들고 C #에서 매개 변수를 사용하여 호출하는 가장 좋은 방법입니까?

using (var conn = new SqlConnection(connStr))
using (var command = new SqlCommand("StoredProc", conn) { CommandType = CommandType.StoredProcedure }) {
   conn.Open();
   command.ExecuteNonQuery();
   conn.Close();
}

8
"코드에 SQL 쿼리가있는 것은 좋지 않다는 것을 알고 있습니다." -이모, 말도 안돼.
GrandmasterB

4
using 블록에서 conn.Close ()를 만든 경우에는 호출 할 필요가 없습니다. using 블록의 요점은 C ++ 스타일의 소멸자 정리를 모방하는 것입니다. 더 문명화 된 시대부터 우아한 청소. try-catch 스타일만큼 무작위이거나 서투른 것은 아닙니다.
Lord Tydus

2
참고로 저장 프로시 저도 "코드"입니다. 저장된 procs의 요점은 절차 코드를 세트 기반 스타일 SQL과 혼합하는 것입니다. 따라서 코드에 관계없이 쿼리가 있습니다. 볼륨이 매우 큰 앱의 경우 서버를 추가하여 수평 확장을 허용하기 위해 데이터베이스 외부에서 로직을 수행하는 것이 좋습니다. 단일 DB를 유지 관리 할 수 ​​있지만 논리에 대한 멀티 서버는 확장이 훨씬 쉬워집니다.
Tydus 경

@GrandmasterB 우리는 C #에 상당한 양의 SQL 인라인을 보유하고 있습니다 (우리의 C # LOC는 현재 2 백만에 가깝습니다). 그리고 6 년 후에 인라인 SQL을 찾아야하기 때문에 우리를 물러서 고 있습니다 (최근에 SQL 전문가를 고용했습니다) -그래서 우리는 성능 조정을하고 있습니다). 날 믿어 : 당신은 당신의 앱이 얼마나 큰지, 앞으로 어떻게 될지 알지 못합니다. 리소스를 명시하기 위해 다른 언어를 다른 파일에 보관하십시오. 당신은 또한 // SQLCODE그것을 할 수 있습니다 -그러나 당신 은 그것을 기억해야합니다.
Jonathan Dickinson

1
@JonathanDickinson, 원하는 경우 저장된 procs를 사용하십시오. 동일한 데이터베이스에 대해 서로 다른 코드베이스를 운영 할 때 유용하다고 여러 번 말했습니다. 그러나 일부 환경 에서 유용하다고 해서 항상 '나쁜 습관'을 사용 하지 않는 것은 아닙니다 . SQL 문을 직접 사용해도 문제가 발생하지 않으면 해당 앱에 대한 '나쁜 습관'이 아닙니다.
GrandmasterB

답변:


10

저장 프로 시저를 사용하는 방법 중 하나이며 수년 동안 널리 사용되었습니다.

C # (또는 .NET 언어)에서 SQL Server 데이터베이스와 상호 작용하는보다 현대적인 방법은 Entity Framework를 사용하는 것입니다. Entity Framework의 장점은 더 높은 수준의 추상화를 제공한다는 것입니다.

Microsoft에서 인용하려면 ( https://msdn.microsoft.com/en-us/data/jj590134 ) :

개발자는 ADO.NET Entity Framework를 사용하여 관계형 저장소 스키마를 직접 프로그래밍하는 대신 개념적 응용 프로그램 모델을 프로그래밍하여 데이터 액세스 응용 프로그램을 만들 수 있습니다. 데이터 지향 응용 프로그램에 필요한 코드 및 유지 관리 비용을 줄이는 것이 목표입니다. Entity Framework 응용 프로그램은 다음과 같은 이점을 제공합니다.

  • 응용 프로그램은 상속, 복잡한 멤버 및 관계가있는 유형을 포함하여보다 응용 프로그램 중심의 개념적 모델 측면에서 작동 할 수 있습니다.
  • 응용 프로그램은 특정 데이터 엔진 또는 스토리지 스키마에 대한 하드 코딩 된 종속성이 없습니다.
  • 개념적 모델과 저장소 별 스키마 간의 매핑은 응용 프로그램 코드를 변경하지 않고도 변경할 수 있습니다.
  • 개발자는 다양한 데이터베이스 관리 시스템에서 구현 될 수있는 다양한 저장소 스키마에 매핑 될 수있는 일관된 응용 프로그램 개체 모델을 사용할 수 있습니다.
  • 여러 개념적 모델을 단일 스토리지 스키마에 매핑 할 수 있습니다.
  • LINQ (언어 통합 쿼리) 지원은 개념적 모델에 대한 쿼리에 대한 컴파일 타임 구문 유효성 검사를 제공합니다.

ORM과 저장 프로 시저 (Stored Procedures)의 사용은 특히 보안 측면과 논리가 존재하는 위치에서 트레이드 오프를 수반합니다.

SQL Server를 사용한 개발에 대한 "전통적인"접근 방식은 응용 프로그램 논리가 저장 프로 시저와 테이블에 직접 업데이트되지 않고 저장 프로 시저를 실행할 수있는 보안 권한 만있는 프로그램에만 상주하는 것입니다. 여기서 개념은 저장 프로 시저가 응용 프로그램의 비즈니스 논리 계층이라는 것입니다. 이론은 건전하지만 C #이나 VB와 같은 프로그래밍 언어로 비즈니스 로직을 구현하는 것으로 대체되면서 여러 가지 이유로 유리하지 않은 경향이 있습니다. 좋은 응용 프로그램은 우려 분리 등을 포함하여 계층 적 접근 방식으로 여전히 구현되지만 MVC와 같은 패턴을 따르는 경향이 있습니다.

데이터베이스가 아닌 ORM에서 로직을 구현할 때의 단점은 데이터베이스 (DA 또는 DBA)를 담당하는 사람들이 데이터 무결성 규칙을 쉽게 디버깅하고 테스트 할 수 있다는 것입니다. 당신의 당좌 예금에서 저축 예금 계좌로 돈을 이체하는 전형적인 예를 들어 보자. 이것은 원자 단위의 작업 단위로, 즉 거래에 끼워진 것이 중요합니다. 이러한 종류의 전송이 저장 프로 시저를 통해서만 수행 될 수있는 경우, DA와 감사자가 저장 프로 시저를 QA하는 것이 비교적 쉽습니다.

반면에 Entity Framework와 같은 ORM을 통해이 작업을 수행하고 프로덕션 환경에서 드물게는 검사에서 돈을 받지만 저축에 들어 가지 않는 경우는 더욱 복잡 할 수 있습니다. 특히 여러 프로그램이 잠재적으로 관련되어있는 경우 더욱 그렇습니다. 이것은 아마도 특정 순서 등에서 발생해야하는 독특한 하드웨어 문제와 관련하여 가장 중요한 경우 일 것입니다. 어떻게 이것을 테스트합니까?


또는 다른 ORM. EF와 비교할 때 다양한 장점과 단점이있는 많은 것들이 있습니다.
svick

8
ORM의 단점을 나열하면이 답변이 더 유용합니다.
Den

6

실제로 기본 주장은 논란의 여지가 있습니다. 코드에 SQL을 사용하거나 데이터베이스에 코드를 저장하는 것 (저장 프로 시저로 향하는 곳) 간에는 상충 관계가 있습니다.

단 하나의 "최고"가 없다는 결론은 어떤 방식 으로든 타협하고 있기 때문에 일반화 할 수있는 것이 아닙니다 (이익을 얻지 만 제약을 초래합니다).

응용 프로그램과 데이터베이스 사이에 일대일 대응 관계가 있다면 실제로 중요하지 않습니다. 반면에 많은 수의 응용 프로그램이 공유하는 큰 코어 데이터베이스가 있으면 해당 응용 프로그램간에 데이터베이스 내에서 일관성을 유지하는 것이 훨씬 중요해집니다.

더 중요한 것은 Entity Framework 또는 NHibernate와 같은 ORM을 사용하거나 더 직접적인 무언가를 수행하는지 여부에 관계없이 적절한 데이터 액세스 계층을 고려할 때 응용 프로그램의 아키텍처 및 계층화에 대해 걱정하는 것입니다. 또는 저장 프로 시저를 사용하십시오.


저는 소규모 팀 (1 ~ 3 명)으로 비교적 소규모 프로젝트를 진행하는 경향이 있습니다. 스토어드 프로 시저를 사용하는 것은 애플리케이션 (및 스킬 셋)의 특성상 새로운 배포를 고려할 때 그 가치보다 더 큰 문제입니다. 코드는 일반적으로 스키마를 업데이트하는 것보다 훨씬 쉬우 며 (스키마를 비교적 간단하게 업데이트하는 코드를 가지고 있음에도 불구하고) 일반적인 데이터 액세스 코드를 사용하여 비즈니스 규칙을 시행 할 수 있습니다. 이것은 "마일리지가 다를 수 있습니다"라는 고전적인 예입니다.


2
"단일 최고 없음"의 경우 +1, 코드 배포의 경우 -1은 저장된 proc 변경 사항을 배포하는 것보다 쉽고, +1은 앱에 적합한 접근 방식을 선택하고 DAL 격리를 보장합니다. 따라서 +1입니다.
Joel Brown

내가 함께 배포 비트 자격을했다 "나에 대해"그 때문에 나를 위해 지속적으로 (특히 웹 응용 프로그램)의 경우이었다 - 모든 것은 그 지역에서 재 작성의 비트를 부담 할 수있다.
Murph

+1, 가장 좋은 것은 응용 프로그램 및 상황에 따라 다릅니다.
GrandmasterB

1
작업 환경에 따라 달라집니다. DBA가 프로덕션에서 잠금 상태가되지 않은 경우 대체 저장 프로 시저를 데이터베이스에 삭제하는 것은 매우 쉽습니다. 이를 위해 프로덕션 컨트롤 없이도 새로운 마크 업, 스크립트 및 심지어 컴파일 된 코드를 중앙 집중식 앱으로 옮기는 것도 훨씬 쉬울 수 있습니다.
Joel Brown

@JoelBrown-정확히-아니, 나는 거기에 모든 가정을했다고 확신합니다. 먼저 내 스키마는 버전 제어 (조잡하지만 효과적인 방식으로)되지만 dba는 아니지만 스키마가 일관성이 있어야한다는 것을 알기에 똑똑합니다. 나는 주로 웹 응용 프로그램에서 작업하고 서버를 방문하는 것 외에는 데이터베이스에 액세스 할 수 없지만 한 번의 클릭만으로 응용 프로그램 배포를 줄였습니다 (스키마 업데이트를 배포 목록에,하지만 난 한 항상 코드 업데이트 이상 스키마 업데이트가 더 스트레스 발견 (롤백의 용이성?)
머피

4

입력을 매개 변수화 한 한 모든 접근 방식이 유효합니다. 코드 인수에 대한 쿼리가없는 대부분은 많은 라이브러리가 명령문을 함께 문자열 추가하도록 강요했던 곳입니다 .SQL 주입 공격이 시작된 곳입니다.


1
매개 변수화가 충분합니까? 살균해야 할 필요는 없습니까?
StuperUser

소스와 목적에 따라 다릅니다. 나는 그의 질문을 문자 그대로 취하고 있었고, 그는 일부 매개 변수를 사용하여 읽기 전용입니다. 일반적으로 매개 변수가 올바르게 매개 변수화 된 경우 더티 입력으로 수행하는 최악의 경우 유형 예외가 발생하거나 입력이 잘못되면 결과가 표시되지 않습니다. 소스를 정식으로 취급하지 않으면 삽입이 다르며 일반적으로 유효성 검사가 필요합니다.
Bill

0

모범 사례는 실제로 과장된 것입니다. 좋은 방법이 많이 있으며, 실제로 선택하는 방법은 앱이 무엇인지, 무엇을해야하는지에 따라 달라집니다. 즉, 실제로 잘못 할 수있는 것은 두 가지뿐입니다.

  • @Bill이 지적했듯이 항상 쿼리를 매개 변수화해야합니다. 문자열 작성은 SQL 주입을위한 쉬운 벡터 일뿐 아니라 버그를 추적하기 어려운 모든 방식입니다. 훨씬 똑똑한 사람들은 SQL을 tupelize하고 탈출하는 방법을 알아 냈으므로 스스로 알아낼 필요가 없습니다.

  • 연결을 닫습니다. 가장 좋은 방법은 using 문을 모두 감싸는 것이지만, 보트를 띄우면 시도 / catch / 마침내 시원합니다. 그러나 항상 싼 차처럼 연결을 사용하십시오. 단단하고 빠르게 운전하고 빨리 제거하십시오.

내가 맹렬히 주장하는 다른 관행은 가능한 한 적은 수의 장소에 데이터 액세스 코드를 집중시켜야한다는 것입니다. 이 경고를 적용하기 위해 프런트 엔드 웹 앱에서 System.Data.SqlClient에 대한 직접 참조를 보유 할 수 없습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.