Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
I parametri inviano valori a un comando separatamente dal suo testo Transact-SQL (T-SQL). Usa oggetti SqlParameter invece di concatenare o interpolare valori nelle istruzioni SQL. I parametri aiutano a proteggere contro l'iniezione SQL e a preservare il tipo di database del valore.
Gli esempi in questo articolo presuppongono che un oggetto connection aperto denominato SqlConnection faccia riferimento al database di esempio AdventureWorks.
Gli esempi di C# richiedono using Microsoft.Data.SqlClient;. Esempi che utilizzano SqlDbType richiedono anche using System.Data;.
Aggiungi parametri di input
Aggiungi un parametro per ogni segnaposto di valore nel testo del comando. Specifica il tipo di SQL Server del parametro e assegna il suo valore:
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})");
}
Usa la stessa combinazione di maiuscole e minuscole per il nome di un parametro nel testo del comando e nel SqlParameter. SQL Server abbina i nomi delle variabili usando la collation del server, quindi una discrepanza fallisce con un errore "Must declare the scalar variable" su un server con una collation con distinzione tra maiuscole e minuscole.
Utilizzare i segnaposto dei parametri
Microsoft. Data.SqlClient utilizza parametri nominati nella forma @parameterName. I segnaposto posizionali (?) non sono supportati.
I segnaposto dei parametri rappresentano valori, non identificatori SQL o sintassi SQL. Non puoi usare un parametro per il nome di una tabella, un nome di colonna, una direzione di ordinamento o un intero frammento SQL. Se un'applicazione seleziona dinamicamente un identificatore, validarlo rispetto a una lista di permessi e aggiungerlo al testo del comando solo dopo la validazione. Continua a passare tutti i valori dei dati come parametri.
Per i comandi testuali, Microsoft. Data.SqlClient invia istruzioni parametrizzate a SQL Server tramite sp_executesql. SQL Server può riutilizzare un piano di esecuzione quando il testo dell'istruzione e le definizioni dei parametri rimangono gli stessi.
Specificare i tipi di dati per i parametri
Impostare SqlDbType esplicitamente quando l'applicazione conosce il tipo di SQL Server di destinazione. Imposta anche metadati specifici per tipo come Size, Precision, e Scale quando applicabile.
Questo esempio corrisponde alle colonne nvarchar(50) e datetime in Person.Person:
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);
Abbinare i metadati dei parametri alla colonna di destinazione evita conversioni implicite e impedisce che variazioni nella lunghezza della stringa o nella scala decimale modifichino la definizione del parametro.
Per i valori decimali, imposta esplicitamente la precisione e la scala. La Weight colonna in Production.Product usa 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;
Passare i valori NULL del database
Assegna Value per l'invio di un database NULL. C# null non rappresenta un SQL Server NULL per parametri scalari ordinari:
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;
Usa i metadati inferiti in modo selettivo
Il AddWithValue metodo deduce i metadati dei parametri dal valore di runtime. L'inferenza è comoda quando i metadati inferiti sono stabili e corrispondono al tipo di database. Può produrre definizioni di parametri diverse quando la lunghezza delle stringhe, la precisione decimale o altre caratteristiche di valore cambiano.
Preferisci Add con un esplicito SqlDbType per comandi di produzione il cui schema target è noto. Non passare C# null a AddWithValue; specifica il tipo e assegna DBNull.Value invece.
Riutilizza i parametri del comando
Crea un parametro una volta e cambialo solo Value quando esegui lo stesso comando con valori diversi:
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)}");
}
}
Non aggiungere un altro parametro con lo stesso nome ad ogni esecuzione. Riutilizza il parametro esistente o cancella la collezione prima di ricostruirla.
Impostare la direzione del parametro
La Direction proprietà identifica come un comando utilizza un parametro. Impostarlo su un valoreParameterDirection:
| Direction | Utilizza |
|---|---|
| Input | Invia un valore a un'istruzione o a una procedura archiviata. Si tratta del valore predefinito. |
| Output | Riceve un valore da un parametro di output di una stored procedure. |
| InputOutput | Invia un valore iniziale e riceve il valore aggiornato. |
| ReturnValue | Riceve il valore intero da un'istruzione T-SQL RETURN . |
Per i parametri di output, input/output e valore di ritorno, leggere Value solo dopo la fine del comando. Se un comando restituisce righe, chiudi o rilascia SqlDataReader prima di leggere quei valori.
Per esempi completi di stored procedure, vedi Modificare i dati con stored procedure.
Usa parametri con una procedura archiviata
Imposta StoredProcedure e usa i nomi dei parametri della procedura. Questo esempio chiama la dbo.uspGetEmployeeManagers procedura inclusa in AdventureWorks:
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)}");
}
Il nome del parametro deve corrispondere a quello dichiarato dalla procedura memorizzata.
Configurare i parametri con valori di tabella
Un parametro con valori di tabella invia più righe a una stored procedure o a un'istruzione parametrizzata. Per configurarne uno:
- Imposta
SqlDbType.Structured. - Impostare TypeName al tipo di tabella definito dall'utente del database.
- Assegna un'origine riga DataTable, DbDataReader o
IEnumerable<SqlDataRecord>.
A DataTable con colonne definite e nessuna riga invia una tabella vuota. Un IEnumerable<SqlDataRecord> vuoto genera ArgumentException; assegna a C# null il valore necessario per inviare zero righe per quel modulo di input. Non assegnare DBNull.Value a un parametro con valori di tabella.
Per la creazione di tipi, la mappatura delle righe e esempi completi, vedi Parametri a valori di tabella.
Configura i valori di streaming
Assegna un Stream, TextReader o XmlReader a Value per incrementare gradualmente di un valore elevato. Per il trasferimento con memoria limitata, si utilizza un tipo di parametro (max), xml o json. Microsoft.Data.SqlClient memorizza la sorgente nel buffer prima dell'esecuzione per i tipi di caratteri e binari non-(max) e i tipi legacy di oggetti di grandi dimensioni.
Il tipo di parametro deve corrispondere al valore:
| Value | Valori compatibili SqlDbType |
|---|---|
| Stream |
Binary, VarBinary, o il tipo legacy Image |
| TextReader |
Char, NChar, NVarChar, VarChar, i tipi legacy Text e NText, Xml, o Json |
| XmlReader |
Char, NChar, NVarChar, VarChar, i tipi legacy Text e NText, Xml, o Json |
Microsoft. Data.SqlClient lancia ArgumentException, InvalidCastException o SqlTypeException quando il tipo di oggetto, SqlDbType o le dimensioni dichiarate siano incompatibili. Per esempi completi di upload e download, vedi il supporto allo streaming SqlClient.
Derivare le informazioni sui parametri
DeriveParametersinterroga SQL Server per i metadati dei parametri di una procedura memorizzata e sostituisce la collezione di parametri esistente del comando:
using var command = new SqlCommand(
"dbo.uspGetEmployeeManagers",
connection);
command.CommandType = CommandType.StoredProcedure;
SqlCommandBuilder.DeriveParameters(command);
command.Parameters["@BusinessEntityID"].Value = 6;
DeriveParameters richiede un round trip aggiuntivo al database ogni volta che viene chiamato. Ricava i metadati durante lo sviluppo quando necessario, poi definisci esplicitamente i parametri nei percorsi critici per le prestazioni.