Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
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 och återanvändning av körningsplan och Parametrar och återanvändning av körningsplaner. 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 sin konstruktor eller genom att lägga till det i DbParameterCollection-samlingen genom att anropa Add-metoden för DbParameterCollection-samlingen. Metoden Add tar som indata antingen konstruktorargument eller ett befintligt parameterobjekt, beroende på dataprovidern.
Förse 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.
| Dataleverantör | 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 datatyper för parametrar
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 ValueParameter objektet eller från DbTypeParameter 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 | Boolesk | Bit | Boolesk | 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 | Rå |
| Char | Det går inte att härleda en SqlDbType från char. | Öring | Öring | byte | |
| DateTime | Datum/tid | Datum/tid | DBTimeStamp | Datum/tid | Datum/tid |
| DateTimeOffset | DateTimeOffset (tidpunkt med tidsförskjutning) | 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 | Singel | Verklig | Singel | Verklig | Flyttal |
| Guid | Guide | UniqueIdentifier | Guide | UniqueIdentifier | Rå |
| 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. | Blobb |
| String | Sträng | 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 | |
| AnsiSträngFastLängd | Öring | Öring | Öring | Öring | |
| Valuta | Pengar | 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 ett SqlDbType från datum i versioner av SQL Server tidigare än SQL Server 2008. | Databasdatum | Datum | 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 | |
| SträngMedFastLängd | NChar | WChar | NChar | NChar | |
| Tid | Tid i SQL Server 2008. Att dra en slutsats från SqlDbType från tidvärden stöds inte på 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 information om parametrar
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 av sp_executesql, 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($"{reader[0]}: {reader[1]:C}");
}
}
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
Att använda parametrar med en OleDbCommand eller en 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;