.NET Framework
ADO.NET
Sök…
Introduktion
ADO (ActiveX Data Objects) .Net är ett verktyg som tillhandahålls av Microsoft som ger tillgång till datakällor som SQL Server, Oracle och XML genom dess komponenter. .Net-front-end-applikationer kan hämta, skapa och manipulera data när de är anslutna till en datakälla via ADO.Net med lämpliga behörigheter.
ADO.Net tillhandahåller en anslutningsfri arkitektur. Det är ett säkert sätt att interagera med en databas, eftersom anslutningen inte behöver upprätthållas under hela sessionen.
Anmärkningar
En notering om att parametrisering SQL-satser med Parameters.AddWithValue
: AddWithValue
är aldrig en bra startpunkt. Den metoden bygger på slutsatsen om typen av data från det som skickas in. Med detta kan du hamna i en situation där konverteringen förhindrar att din fråga använder ett index . Observera att vissa SQL Server-datatyper, t.ex. char
/ varchar
(utan föregående "n") eller date
inte har en motsvarande .NET-datatyp. I dessa fall bör Add
med rätt datatyp användas istället .
Utför SQL-satser som ett kommando
// Uses Windows authentication. Replace the Trusted_Connection parameter with
// User Id=...;Password=...; to use SQL Server authentication instead. You may
// want to find the appropriate connection string for your server.
string connectionString = @"Server=myServer\myInstance;Database=myDataBase;Trusted_Connection=True;"
string sql = "INSERT INTO myTable (myDateTimeField, myIntField) " +
"VALUES (@someDateTime, @someInt);";
// Most ADO.NET objects are disposable and, thus, require the using keyword.
using (var connection = new SqlConnection(connectionString))
using (var command = new SqlCommand(sql, connection))
{
// Use parameters instead of string concatenation to add user-supplied
// values to avoid SQL injection and formatting issues. Explicitly supply datatype.
// System.Data.SqlDbType is an enumeration. See Note1
command.Parameters.Add("@someDateTime", SqlDbType.DateTime).Value = myDateTimeVariable;
command.Parameters.Add("@someInt", SqlDbType.Int).Value = myInt32Variable;
// Execute the SQL statement. Use ExecuteScalar and ExecuteReader instead
// for query that return results (or see the more specific examples, once
// those have been added).
connection.Open();
command.ExecuteNonQuery();
}
Obs 1: Se SqlDbType-uppräkning för MSFT SQL Server-specifik variation.
Obs 2: Se MySqlDbType-uppräkning för den MySQL-specifika variationen.
Bästa praxis - Utföra SQL-uttalanden
public void SaveNewEmployee(Employee newEmployee)
{
// best practice - wrap all database connections in a using block so they are always closed & disposed even in the event of an Exception
// best practice - retrieve the connection string by name from the app.config or web.config (depending on the application type) (note, this requires an assembly reference to System.configuration)
using(SqlConnection con = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["MyConnectionName"].ConnectionString))
{
// best practice - use column names in your INSERT statement so you are not dependent on the sql schema column order
// best practice - always use parameters to avoid sql injection attacks and errors if malformed text is used like including a single quote which is the sql equivalent of escaping or starting a string (varchar/nvarchar)
// best practice - give your parameters meaningful names just like you do variables in your code
using(SqlCommand sc = new SqlCommand("INSERT INTO employee (FirstName, LastName, DateOfBirth /*etc*/) VALUES (@firstName, @lastName, @dateOfBirth /*etc*/)", con))
{
// best practice - always specify the database data type of the column you are using
// best practice - check for valid values in your code and/or use a database constraint, if inserting NULL then use System.DbNull.Value
sc.Parameters.Add(new SqlParameter("@firstName", SqlDbType.VarChar, 200){Value = newEmployee.FirstName ?? (object) System.DBNull.Value});
sc.Parameters.Add(new SqlParameter("@lastName", SqlDbType.VarChar, 200){Value = newEmployee.LastName ?? (object) System.DBNull.Value});
// best practice - always use the correct types when specifying your parameters, Value is assigned to a DateTime instance and not a string representation of a Date
sc.Parameters.Add(new SqlParameter("@dateOfBirth", SqlDbType.Date){ Value = newEmployee.DateOfBirth });
// best practice - open your connection as late as possible unless you need to verify that the database connection is valid and wont fail and the proceeding code execution takes a long time (not the case here)
con.Open();
sc.ExecuteNonQuery();
}
// the end of the using block will close and dispose the SqlConnection
// best practice - end the using block as soon as possible to release the database connection
}
}
// supporting class used as parameter for example
public class Employee
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
}
Bästa praxis för att arbeta med ADO.NET
- Tumregeln är att öppna anslutningen under minimal tid. Stäng anslutningen uttryckligen när din procedurutförande har slutförts kommer det att ansluta objektet tillbaka till anslutningspoolen Standard anslutning pool max storlek = 100. Eftersom anslutning pooling förbättrar prestandan för fysisk anslutning till SQL Server. Anslutning Pooling i SQL Server
- Packa in alla databasanslutningar i ett användningsblock så att de alltid är stängda och bortskaffade även i händelse av ett undantag. Se användning av uttalande (C # referens) för mer information om hur du använder uttalanden
- Hämta anslutningssträngarna efter namn från app.config eller web.config (beroende på applikationstyp)
- Detta kräver en monteringsreferens till
System.configuration
- Se Anslutningssträngar och konfigurationsfiler för ytterligare information om hur du strukturerar din konfigurationsfil
- Detta kräver en monteringsreferens till
- Använd alltid parametrar för inkommande värden till
- Undvik SQL-injektionsattacker
- Undvik fel om felformad text används som att inkludera en enda offert som är den ekvivalenta sql för att komma undan eller starta en sträng (varchar / nvarchar)
- Att låta databasleverantören återanvända frågeflaner (stöds inte av alla databasleverantörer) vilket ökar effektiviteten
- När du arbetar med parametrar
- Sql-parametrar typ och felstorlek är en vanlig orsak till att infoga / uppdatera / välja fel
- Ge dina Sql-parametrar meningsfulla namn precis som du gör variabler i din kod
- Ange databasdatatypen för kolumnen du använder, detta säkerställer att felaktiga parametertyper inte används vilket kan leda till oväntade resultat
- Validera dina inkommande parametrar innan du skickar dem in i kommandot (som ordspråket säger, " skräp in, skräp ut "). Validera inkommande värden så tidigt som möjligt i bunten
- Använd rätt typer när du tilldelar dina parametervärden, exempel: tilldela inte strängvärdet för en DateTime, istället tilldelar en faktisk DateTime-instans till parametervärdet
- Ange storleken på parametrarna för strängtyp. Detta beror på att SQL Server kan använda exekveringsplaner om parametrarna matchar typ och storlek. Använd -1 för MAX
- Använd inte metoden AddWithValue , huvudorsaken är att det är väldigt lätt att glömma att ange parametertypen eller precisionen / skalan vid behov. Mer information finns i Kan vi sluta använda AddWithValue redan?
- När du använder databasanslutningar
- Öppna anslutningen så sent som möjligt och stäng den så snart som möjligt. Detta är en allmän riktlinje när du arbetar med någon extern resurs
- Dela aldrig databasanslutningstillfällen (exempel: att ha en singleton värd för en delad instans av typen
SqlConnection
). Låt din kod alltid skapa en ny databasanslutningsinstans när det behövs och låt sedan ringkoden kassera den och "släng den" när den är klar. Anledningen till detta är- De flesta databasleverantörer har någon form av anslutningspooler så det är billigt att skapa nya hanterade anslutningar
- Det eliminerar eventuella framtida fel om koden börjar fungera med flera trådar
Använda vanliga gränssnitt för att abstrahera leverantörsspecifika klasser
var providerName = "System.Data.SqlClient"; //Oracle.ManagedDataAccess.Client, IBM.Data.DB2
var connectionString = "{your-connection-string}";
//you will probably get the above two values in the ConnectionStringSettings object from .config file
var factory = DbProviderFactories.GetFactory(providerName);
using(var connection = factory.CreateConnection()) { //IDbConnection
connection.ConnectionString = connectionString;
connection.Open();
using(var command = connection.CreateCommand()) { //IDbCommand
command.CommandText = "{query}";
using(var reader = command.ExecuteReader()) { //IDataReader
while(reader.Read()) {
...
}
}
}
}