Konfigurera parametrar och parameterdatatyper
Kommandoobjekt använder parametrar för att skicka värden till SQL-instruktioner eller lagrade procedurer, vilket ger typkontroll och validering. Till skillnad från kommandotext behandlas parameterindata som ett literalvärde, inte som körbar kod. Detta skyddar mot "SQL-inmatningsattacker", där en angripare infogar ett kommando som äventyrar säkerheten på servern i en SQL-instruktion.
Parametriserade kommandon kan också förbättra frågekörningsprestanda, eftersom de hjälper databasservern att korrekt matcha det inkommande kommandot med en korrekt cachelagrad frågeplan. Mer information finns i Cachelagring av körningsplan, återanvändning och parametrar och återanvändning av körningsplan. Utöver säkerhets- och prestandafördelarna ger parametriserade kommandon en praktisk metod för att organisera värden som skickas till en datakälla.
Ett DbParameter objekt kan skapas med hjälp av konstruktorn eller genom att lägga till det i genom att DbParameterCollection anropa Add
metoden för DbParameterCollection samlingen. Metoden Add
tar som indata antingen konstruktorargument eller ett befintligt parameterobjekt, beroende på dataprovidern.
Ange egenskapen ParameterDirection
När du lägger till parametrar måste du ange en ParameterDirection egenskap för andra parametrar än indataparametrar. I följande tabell visas de ParameterDirection
värden som du kan använda med ParameterDirection uppräkningen.
Medlemsnamn | beskrivning |
---|---|
Input | Parametern är en indataparameter. Det här är standardinställningen. |
InputOutput | Parametern kan utföra både indata och utdata. |
Output | Parametern är en utdataparameter. |
ReturnValue | Parametern representerar ett returvärde från en åtgärd, till exempel en lagrad procedur, inbyggd funktion eller användardefinierad funktion. |
Arbeta med platshållare för parametrar
Syntaxen för parameterplatshållare beror på datakällan. .NET Framework-dataprovidrar hanterar namngivning och anger parametrar och parameterplatshållare på olika sätt. Den här syntaxen anpassas till en specifik datakälla enligt beskrivningen i följande tabell.
Dataprovider | Parameternamnssyntax |
---|---|
System.Data.SqlClient | Använder namngivna parametrar i formatet @ parameternamn. |
System.Data.OleDb | Använder positionsparametermarkörer som anges av ett frågetecken (? ). |
System.Data.Odbc | Använder positionsparametermarkörer som anges av ett frågetecken (? ). |
System.Data.OracleClient | Använder namngivna parametrar i formatet : parmname (eller parmname). |
Ange parameterdatatyper
Datatypen för en parameter är specifik för .NET Framework-dataprovidern. Om du anger typen konverteras värdet Parameter
för till .NET Framework-dataprovidertypen innan värdet skickas till datakällan. Du kan också ange typen av en Parameter
på ett allmänt sätt genom att ange DbType
egenskapen för Parameter
objektet till en viss DbType.
.NET Framework-dataprovidertypen för ett Parameter
objekt härleds från .NET Framework-typen för Value
Parameter
objektet eller från DbType
Parameter
objektets. I följande tabell visas den härledda Parameter
typen baserat på objektet som skickas som Parameter
värdet eller den angivna DbType
.
.NET Framework-typ | DbType | SqlDbType | OleDbType | OdbcType | OracleType |
---|---|---|---|---|---|
Boolean | Booleskt | Bit | Booleskt | Bit | Byte |
Byte | Byte | TinyInt | UnsignedTinyInt | TinyInt | Byte |
byte[] | Binära | VarBinary. Den här implicita konverteringen misslyckas om bytematrisen är större än den maximala storleken för en VarBinary, som är 8 000 byte. För bytematriser som är större än 8 000 byte anger du uttryckligen SqlDbType. | VarBinary | Binära | Raw |
Char | Det går inte att härleda en SqlDbType från tecken. | Char | Char | Byte | |
DateTime | Datum/tid | Datum/tid | DBTimeStamp | Datum/tid | Datum/tid |
DateTimeOffset | DateTimeOffset | DateTimeOffset i SQL Server 2008. Det går inte att härleda en SqlDbType från DateTimeOffset i versioner av SQL Server tidigare än SQL Server 2008. | Datum/tid | ||
Decimal | Decimal | Decimal | Decimal | Numerisk | Antal |
Double | Dubbel | Flyttal | Dubbel | Dubbel | Dubbel |
Single | Enstaka | Real | Enstaka | Real | Flyttal |
Guid | GUID | UniqueIdentifier | GUID | UniqueIdentifier | Raw |
Int16 | Int16 | SmallInt | SmallInt | SmallInt | Int16 |
Int32 | Int32 | Int | Int | Int | Int32 |
Int64 | Int64 | BigInt | BigInt | BigInt | Antal |
Object | Objekt | Variant | Variant | Det går inte att härleda en OdbcType från objekt. | Blob |
String | String | NVarChar. Den här implicita konverteringen misslyckas om strängen är större än den maximala storleken för ett NVarChar, vilket är 4 000 tecken. För strängar som är större än 4 000 tecken anger du uttryckligen SqlDbType. | VarWChar | NVarChar | NVarChar |
TimeSpan | Tid | Tid i SQL Server 2008. Det går inte att härleda en SqlDbType från TimeSpan i tidigare versioner av SQL Server än SQL Server 2008. | DBTime | Tid | Datum/tid |
UInt16 | UInt16 | Det går inte att härleda en SqlDbType från UInt16. | UnsignedSmallInt | Int | UInt16 |
UInt32 | UInt32 | Det går inte att härleda en SqlDbType från UInt32. | OsigneradInt | BigInt | UInt32 |
UInt64 | UInt64 | Det går inte att härleda en SqlDbType från UInt64. | UnsignedBigInt | Numerisk | Antal |
AnsiString | VarChar | VarChar | VarChar | VarChar | |
AnsiStringFixedLength | Char | Char | Char | Char | |
Valuta | Money | Valuta | Det går inte att härleda en OdbcType från Currency . |
Antal | |
Datum | Datum i SQL Server 2008. Det går inte att härleda från SqlDbType Datum i versioner av SQL Server tidigare än SQL Server 2008. | DBDate | Date | Datum/tid | |
SByte | Det går inte att härleda en SqlDbType från SByte. | TinyInt | Det går inte att härleda en OdbcType från SByte. |
SByte | |
StringFixedLength | NChar | WChar | NChar | NChar | |
Tid | Tid i SQL Server 2008. Slutsatsdragning SqlDbType från tid stöds inte i versioner av SQL Server tidigare än SQL Server 2008. | DBTime | Tid | Datum/tid | |
VarNumeric | Det går inte att härleda en SqlDbType från VarNumeric. | VarNumeric | Det går inte att härleda en OdbcType från VarNumeric. |
Antal | |
användardefinierad typ (ett objekt med SqlUserDefinedAggregateAttribute | Objekt eller sträng, beroende på providern (SqlClient returnerar alltid ett objekt, Odbc returnerar alltid en sträng och OleDb-hanterad dataprovider kan se antingen | SqlDbType.Udt om SqlUserDefinedTypeAttribute finns, annars Variant | OleDbType.VarWChar (om värdet är null) annars OleDbType.Variant. | OdbcType.NVarChar | stöds inte |
Kommentar
Konverteringar från decimal till andra typer begränsar konverteringar som avrundar decimalvärdet till närmaste heltalsvärde mot noll. Om resultatet av konverteringen inte kan representeras i måltypen genereras en OverflowException .
Kommentar
När du skickar ett null-parametervärde till servern måste du ange DBNull, inte null
(Nothing
i Visual Basic). Null-värdet i systemet är ett tomt objekt som inte har något värde. DBNull används för att representera null-värden. Mer information om null-databaser finns i Hantera nullvärden.
Härleda parameterinformation
Parametrar kan också härledas från en lagrad procedur med hjälp av DbCommandBuilder
klassen . Både klasserna SqlCommandBuilder
och OleDbCommandBuilder
tillhandahåller en statisk metod, DeriveParameters
, som automatiskt fyller i parametersamlingen för ett kommandoobjekt som använder parameterinformation från en lagrad procedur. Observera att DeriveParameters
skriver över all befintlig parameterinformation för kommandot.
Kommentar
Att härleda parameterinformation medför en prestandaavgift eftersom det krävs ytterligare en tur- och returresa till datakällan för att hämta informationen. Om parameterinformationen är känd vid designtillfället kan du förbättra programmets prestanda genom att uttryckligen ange parametrarna.
Mer information finns i Generera kommandon med CommandBuilders.
Använda parametrar med en SqlCommand och en lagrad procedur
Lagrade procedurer erbjuder många fördelar i datadrivna program. Genom att använda lagrade procedurer kan databasåtgärder kapslas in i ett enda kommando, optimeras för bästa prestanda och förbättras med ytterligare säkerhet. Även om en lagrad procedur kan anropas genom att skicka namnet på den lagrade proceduren följt av parameterargument som en SQL-instruktion, kan du använda Parameters samlingen av ADO.NET-objektet DbCommand för att mer explicit definiera lagrade procedureparametrar och få åtkomst till utdataparametrar och returvärden.
Kommentar
Parametriserade instruktioner körs på servern med hjälp sp_executesql
av , vilket möjliggör återanvändning av frågeplan. Lokala markörer eller variabler i batchen sp_executesql
är inte synliga för batchen som anropar sp_executesql
. Ändringar i databaskontexten varar endast till slutet av -instruktionen sp_executesql
. Mer information finns i sp_executesql (Transact-SQL).
När du använder parametrar med en SqlCommand för att köra en lagrad SQL Server-procedur måste namnen på de parametrar som läggs till i Parameters samlingen matcha namnen på parametermarkörerna i den lagrade proceduren. .NET Framework-dataprovidern för SQL Server stöder inte platshållaren för frågetecken (?) för att skicka parametrar till en SQL-instruktion eller en lagrad procedur. Den behandlar parametrar i den lagrade proceduren som namngivna parametrar och söker efter matchande parametermarkörer. Den lagrade proceduren definieras till exempel CustOrderHist
med hjälp av en parameter med namnet @CustomerID
. När koden kör den lagrade proceduren måste den också använda en parameter med namnet @CustomerID
.
CREATE PROCEDURE dbo.CustOrderHist @CustomerID varchar(5)
Exempel
Det här exemplet visar hur du anropar en lagrad SQL Server-procedur i exempeldatabasen Northwind
. Namnet på den lagrade proceduren är dbo.SalesByCategory
och har en indataparameter med namnet @CategoryName
med datatypen nvarchar(15)
. Koden skapar en ny SqlConnection i ett användningsblock så att anslutningen tas bort när proceduren avslutas. Objekten SqlCommand och SqlParameter skapas och deras egenskaper anges. A SqlDataReader kör SqlCommand
och returnerar resultatuppsättningen från den lagrade proceduren och visar utdata i konsolfönstret.
Kommentar
I stället för att skapa SqlCommand
och SqlParameter
objekt och sedan ange egenskaper i separata instruktioner kan du i stället välja att använda en av de överlagrade konstruktorerna för att ange flera egenskaper i en enda instruktion.
static void GetSalesByCategory(string connectionString,
string categoryName)
{
using (SqlConnection connection = new(connectionString))
{
// Create the command and set its properties.
SqlCommand command = new()
{
Connection = connection,
CommandText = "SalesByCategory",
CommandType = CommandType.StoredProcedure
};
// Add the input parameter and set its properties.
SqlParameter parameter = new()
{
ParameterName = "@CategoryName",
SqlDbType = SqlDbType.NVarChar,
Direction = ParameterDirection.Input,
Value = categoryName
};
// Add the parameter to the Parameters collection.
command.Parameters.Add(parameter);
// Open the connection and execute the reader.
connection.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
Console.WriteLine("{0}: {1:C}", reader[0], reader[1]);
}
}
else
{
Console.WriteLine("No rows found.");
}
reader.Close();
}
}
}
Shared Sub GetSalesByCategory(ByVal connectionString As String, _
ByVal categoryName As String)
Using connection As New SqlConnection(connectionString)
' Create the command and set its properties.
Dim command As SqlCommand = New SqlCommand()
command.Connection = connection
command.CommandText = "SalesByCategory"
command.CommandType = CommandType.StoredProcedure
' Add the input parameter and set its properties.
Dim parameter As New SqlParameter()
parameter.ParameterName = "@CategoryName"
parameter.SqlDbType = SqlDbType.NVarChar
parameter.Direction = ParameterDirection.Input
parameter.Value = categoryName
' Add the parameter to the Parameters collection.
command.Parameters.Add(parameter)
' Open the connection and execute the reader.
connection.Open()
Using reader As SqlDataReader = command.ExecuteReader()
If reader.HasRows Then
Do While reader.Read()
Console.WriteLine("{0}: {1:C}", _
reader(0), reader(1))
Loop
Else
Console.WriteLine("No rows returned.")
End If
End Using
End Using
End Sub
Använda parametrar med en OleDbCommand eller OdbcCommand
När du använder parametrar med en OleDbCommand eller OdbcCommandmåste ordningen på de parametrar som läggs till i Parameters
samlingen matcha ordningen på de parametrar som definierats i den lagrade proceduren. .NET Framework-dataprovidern för OLE DB och .NET Framework Data Provider för ODBC behandlar parametrar i en lagrad procedur som platshållare och tillämpar parametervärden i ordning. Dessutom måste returnerade värdeparametrar vara de första parametrarna som läggs till i Parameters
samlingen.
.NET Framework-dataprovidern för OLE DB och .NET Framework Data Provider för ODBC stöder inte namngivna parametrar för att skicka parametrar till en SQL-instruktion eller en lagrad procedur. I det här fallet måste du använda platshållaren för frågetecknet (?), som i följande exempel.
SELECT * FROM Customers WHERE CustomerID = ?
Därför måste den ordning i vilken Parameter
objekt läggs till Parameters
i samlingen direkt motsvara positionen för ? platshållare för parametern.
OleDb-exempel
Dim command As OleDbCommand = New OleDbCommand( _
"SampleProc", connection)
command.CommandType = CommandType.StoredProcedure
Dim parameter As OleDbParameter = command.Parameters.Add( _
"RETURN_VALUE", OleDbType.Integer)
parameter.Direction = ParameterDirection.ReturnValue
parameter = command.Parameters.Add( _
"@InputParm", OleDbType.VarChar, 12)
parameter.Value = "Sample Value"
parameter = command.Parameters.Add( _
"@OutputParm", OleDbType.VarChar, 28)
parameter.Direction = ParameterDirection.Output
OleDbCommand command = new OleDbCommand("SampleProc", connection);
command.CommandType = CommandType.StoredProcedure;
OleDbParameter parameter = command.Parameters.Add(
"RETURN_VALUE", OleDbType.Integer);
parameter.Direction = ParameterDirection.ReturnValue;
parameter = command.Parameters.Add(
"@InputParm", OleDbType.VarChar, 12);
parameter.Value = "Sample Value";
parameter = command.Parameters.Add(
"@OutputParm", OleDbType.VarChar, 28);
parameter.Direction = ParameterDirection.Output;
Odbc-exempel
Dim command As OdbcCommand = New OdbcCommand( _
"{ ? = CALL SampleProc(?, ?) }", connection)
command.CommandType = CommandType.StoredProcedure
Dim parameter As OdbcParameter = command.Parameters.Add("RETURN_VALUE", OdbcType.Int)
parameter.Direction = ParameterDirection.ReturnValue
parameter = command.Parameters.Add( _
"@InputParm", OdbcType.VarChar, 12)
parameter.Value = "Sample Value"
parameter = command.Parameters.Add( _
"@OutputParm", OdbcType.VarChar, 28)
parameter.Direction = ParameterDirection.Output
OdbcCommand command = new OdbcCommand( _
"{ ? = CALL SampleProc(?, ?) }", connection);
command.CommandType = CommandType.StoredProcedure;
OdbcParameter parameter = command.Parameters.Add( _
"RETURN_VALUE", OdbcType.Int);
parameter.Direction = ParameterDirection.ReturnValue;
parameter = command.Parameters.Add( _
"@InputParm", OdbcType.VarChar, 12);
parameter.Value = "Sample Value";
parameter = command.Parameters.Add( _
"@OutputParm", OdbcType.VarChar, 28);
parameter.Direction = ParameterDirection.Output;