Microsoft.Data.SqlClient로 매개변수를 구성하세요

매개변수는 명령의 Transact-SQL(T-SQL) 텍스트와는 별도로 값을 전송합니다. SQL 문에 값을 연결하거나 보간하는 대신 SqlParameter 객체를 사용하세요. 매개변수는 SQL 인젝션으로부터 보호하고 값의 데이터베이스 유형을 보존하는 데 도움을 줍니다.

이 글의 예시들은 connection라는 이름의 열려 있는 SqlConnection가 AdventureWorks 샘플 데이터베이스를 대상으로 한다고 가정합니다.

C# 예제에는 using Microsoft.Data.SqlClient;가 필요합니다. SqlDbType를 사용하는 예에는 using System.Data;도 필요합니다.

입력 매개변수 추가

명령어 텍스트에서 각 값 자리 표시자에 대해 매개변수를 추가하세요. 매개변수의 SQL Server 타입을 지정하고 값을 할당합니다:

const string sql = """
    SELECT ProductID, Name, ListPrice
    FROM Production.Product
    WHERE ProductSubcategoryID = @subcategoryId
      AND ListPrice >= @minimumPrice
    ORDER BY ListPrice;
    """;

using var command = new SqlCommand(sql, connection);
command.Parameters.Add("@subcategoryId", SqlDbType.Int).Value = 2;
command.Parameters.Add("@minimumPrice", SqlDbType.Money).Value = 1_000m;

using SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
    Console.WriteLine(
        $"{reader.GetInt32(0)}: {reader.GetString(1)} ({reader.GetDecimal(2):C})");
}

명령어 텍스트와 SqlParameter에서 매개 변수 이름에 동일한 대소문자 표기를 사용하세요. SQL Server는 서버 콜레이션을 사용하여 변수 이름을 일치시키므로, 대소문자를 구분하는 콜레이션을 사용하는 서버에서는 불일치 시 "스칼라 변수를 선언해야 합니다" 오류와 함께 실패합니다.

매개변수 자리 표시자 사용하기

Microsoft.Data.SqlClient는 @parameterName 형식의 명명된 매개 변수를 사용합니다. 위치 지정 물음표(?) 플레이스홀더는 지원되지 않습니다.

매개변수 자리 표시자는 SQL 식별자나 문법이 아닌 값을 나타냅니다. 사용자는 테이블 이름, 열명, 정렬 방향 또는 전체 SQL 조각에 매개변수를 사용할 수 없습니다. 애플리케이션이 동적으로 식별자를 선택하면, 허용 목록에 있는지 검증한 후에만 명령어 텍스트에 추가하세요. 모든 데이터 값을 매개변수로 계속 전달하세요.

텍스트 명령어의 경우, Microsoft.Data.SqlClient는 매개변수화된 문장을 sp_executesql를 통해 SQL Server에 전송합니다. SQL Server는 문장 텍스트와 매개변수 정의가 동일할 때 실행 계획을 재사용할 수 있습니다.

매개 변수 데이터 형식 지정

애플리케이션이 대상 SQL Server 타입을 알고 있을 때 SqlDbType를 명시적으로 설정합니다. 또한 해당되는 경우 Precision, Scale, Size와 같은 타입별 메타데이터를 설정하세요.

이 예시는 Person.Person의 nvarchar(50) 및 datetime 열과 일치합니다:

const string sql = """
    SELECT BusinessEntityID, FirstName, LastName
    FROM Person.Person
    WHERE LastName = @lastName
      AND ModifiedDate >= @modifiedSince
    ORDER BY BusinessEntityID;
    """;

using var command = new SqlCommand(sql, connection);

SqlParameter lastName = command.Parameters.Add(
    "@lastName",
    SqlDbType.NVarChar,
    50);
lastName.Value = "O'Brien";

SqlParameter modifiedSince = command.Parameters.Add(
    "@modifiedSince",
    SqlDbType.DateTime);
modifiedSince.Value = new DateTime(2013, 1, 1);

매개변수 메타데이터를 대상 열과 맞추면 암묵적 변환을 방지하고, 문자열 길이나 십진수 스케일 변경으로 인해 매개변수 정의가 변경되는 것을 방지할 수 있습니다.

소수점 값은 정밀도와 스케일을 명시적으로 설정하세요. Production.Product의 Weight 열은 decimal(8, 2)을 사용합니다:

const string sql = """
    SELECT ProductID, Name, Weight
    FROM Production.Product
    WHERE Weight >= @minimumWeight
    ORDER BY Weight;
    """;

using var command = new SqlCommand(sql, connection);
SqlParameter minimumWeight = command.Parameters.Add(
    "@minimumWeight",
    SqlDbType.Decimal);
minimumWeight.Precision = 8;
minimumWeight.Scale = 2;
minimumWeight.Value = 10.25m;

데이터베이스 NULL 값을 전달합니다

NULL을 할당하여 데이터베이스 Value을 보내세요. C# null 은 일반적인 스칼라 매개변수에 대해 SQL Server NULL 를 나타내지 않습니다:

const string sql = """
    SELECT SalesOrderID, OrderDate, SalesPersonID
    FROM Sales.SalesOrderHeader
    WHERE (@salesPersonId IS NULL OR SalesPersonID = @salesPersonId)
    ORDER BY SalesOrderID;
    """;

using var command = new SqlCommand(sql, connection);
SqlParameter salesPersonId = command.Parameters.Add(
    "@salesPersonId",
    SqlDbType.Int);

int? selectedSalesPersonId = null;
salesPersonId.Value = selectedSalesPersonId.HasValue
    ? selectedSalesPersonId.Value
    : DBNull.Value;

추론된 메타데이터를 선택적으로 사용하세요

AddWithValue 메서드는 런타임 값에서 매개변수 메타데이터를 추론합니다. 추론은 추론된 메타데이터가 안정적이고 데이터베이스 유형과 일치할 때 편리합니다. 문자열 길이, 십진법 정밀도 또는 기타 값 특성이 변할 때 다른 매개변수 정의를 생성할 수 있습니다.

대상 스키마를 알고 있는 프로덕션 명령의 경우 명시적 SqlDbType가 있는 Add를 사용하는 것이 좋습니다. C#을 null에서 AddWithValue로 전달하지 말고, 대신 타입을 지정하고 DBNull.Value에 할당하세요.

명령 매개 변수를 재사용

한 번만 매개변수를 만들고 같은 명령어를 다른 값으로 실행할 때 해당 Value만 변경하세요:

const string sql = """
    SELECT TOP (1) Name, ListPrice
    FROM Production.Product
    WHERE ProductSubcategoryID = @subcategoryId
    ORDER BY ListPrice DESC;
    """;

using var command = new SqlCommand(sql, connection);
SqlParameter subcategoryId = command.Parameters.Add(
    "@subcategoryId",
    SqlDbType.Int);

foreach (int id in new[] { 1, 2, 3 })
{
    subcategoryId.Value = id;

    using SqlDataReader reader = command.ExecuteReader();
    if (reader.Read())
    {
        Console.WriteLine($"{id}: {reader.GetString(0)}");
    }
}

매번 같은 이름의 매개변수를 매번 추가하지 마세요. 기존 매개변수를 재사용하거나 재구성하기 전에 컬렉션을 지우세요.

매개변수 방향 설정

이 속성은 Direction 명령어가 매개변수를 어떻게 사용하는지를 나타냅니다. ParameterDirection값으로 설정합니다:

Direction 사용
Input 값을 문이나 저장 프로시저에 전송합니다. 이 값은 기본값입니다.
Output 저장 프로시저 출력 매개변수로부터 값을 받습니다.
InputOutput 초기 값을 보내고 업데이트된 값을 받습니다.
ReturnValue T-SQL RETURN 문장에서 정수 값을 받습니다.

출력, 입출력, 반환값 매개변수의 경우 Value는 명령이 끝난 후에만 읽으십시오. 명령어가 행을 반환하면, 해당 값을 읽기 전에 SqlDataReader를 닫거나 폐기하세요.

완전한 저장 프로시저 예시는 저장된 프로시저로 데이터를 수정하기를 참조하세요.

저장 프로시저에 매개변수를 사용하세요

StoredProcedure을 설정하고 프로시저의 매개변수 이름을 사용하세요. 이 예시는 AdventureWorks에 포함된 dbo.uspGetEmployeeManagers 절차를 호출합니다:

using var command = new SqlCommand(
    "dbo.uspGetEmployeeManagers",
    connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(
    "@BusinessEntityID",
    SqlDbType.Int).Value = 6;

using SqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
    Console.WriteLine(
        $"{reader.GetString(2)} {reader.GetString(3)}");
}

매개변수 이름은 저장 프로시저에서 선언된 이름과 일치해야 합니다.

테이블 값 매개변수 설정

테이블 값 매개변수는 여러 행을 저장 프로시저 또는 매개변수화된 문에 보냅니다. 하나를 구성하려면:

  1. SqlDbType.Structured을 설정합니다.
  2. TypeName를 데이터베이스 사용자 정의 테이블 타입으로 설정하세요.
  3. DbDataReader, IEnumerable<SqlDataRecord>, 또는 DataTable 행 소스를 할당하세요.

정의된 열이 있고 행이 없는 A DataTable는 빈 테이블을 보냅니다. 빈 IEnumerable<SqlDataRecord>는 ArgumentException를 발생시킵니다. 해당 입력 폼에 대해 0행을 보내려면 C# null 값을 할당합니다. DBNull.Value를 테이블 값 매개변수에 할당하지 마세요.

타입 생성, 행 매핑 및 완전한 예제에 대해서는 Table-valued parameters를 참조하세요.

스트리밍 값 설정

XmlReader, Value 또는 Stream를 TextReader에 할당하여 큰 값을 점진적으로 제공합니다. 유한 메모리 전송의 경우 , xml 또는 (max) 매개변수 유형을 사용합니다. Microsoft.Data.SqlClient는 문자 및 이진이 아닌 형식과 레거시 대형 개체 형식에 대해 실행 전에 소스를 버퍼링합니다.

매개변수 유형은 다음 값과 일치해야 합니다:

Value 호환 SqlDbType 가능한 값
Stream Binary, VarBinary 또는 레거시 Image 타입
TextReader Char, NChar, NVarChar, VarChar, 레거시 Text 및 NText 유형, Xml 또는 Json
XmlReader Char, NChar, NVarChar, VarChar, 레거시 Text와 NText 타입, Xml, 또는 Json

Microsoft.Data.SqlClient는 객체 유형, ArgumentException, 또는 선언된 크기가 호환되지 않을 때 SqlDbType, SqlTypeException, 또는 InvalidCastException 예외를 발생시킵니다. 업로드 및 다운로드 전체 예시는 SqlClient 스트리밍 지원을 참조하세요.

매개변수 정보 도출

DeriveParameters 저장 프로시저의 매개변수 메타데이터를 SQL Server를 쿼리하여 가져오고, 명령의 기존 매개변수 컬렉션을 대체합니다:

using var command = new SqlCommand(
    "dbo.uspGetEmployeeManagers",
    connection);
command.CommandType = CommandType.StoredProcedure;

SqlCommandBuilder.DeriveParameters(command);
command.Parameters["@BusinessEntityID"].Value = 6;

DeriveParameters 호출될 때마다 추가 데이터베이스 왕복이 필요합니다. 개발 과정에서 필요할 때 메타데이터를 도출한 후, 성능에 민감한 경로에 매개변수를 명시적으로 정의합니다.