.NET Framework
ADO.NET
Suche…
Einführung
ADO (ActiveX Data Objects) .Net ist ein Tool von Microsoft, das über seine Komponenten Zugriff auf Datenquellen wie SQL Server, Oracle und XML bietet. .NET-Front-End-Anwendungen können Daten abrufen, erstellen und bearbeiten, sobald sie über ADO.Net mit entsprechenden Datenrechten mit einer Datenquelle verbunden sind.
ADO.Net bietet eine verbindungslose Architektur. Dies ist ein sicherer Ansatz für die Interaktion mit einer Datenbank, da die Verbindung nicht während der gesamten Sitzung aufrechterhalten werden muss.
Bemerkungen
Ein Hinweis zur Parametrisierung von SQL mit Parameters.AddWithValue
: AddWithValue
ist niemals ein guter Ausgangspunkt. Diese Methode beruht darauf, dass der Datentyp aus den übergebenen Daten abgeleitet wird. Dadurch kann es vorkommen, dass die Konvertierung die Verwendung eines Index durch die Konvertierung verhindert. Beachten Sie, dass einige SQL Server-Datentypen, beispielsweise char
/ varchar
(ohne vorangestelltes "n") oder date
, keinen entsprechenden .NET-Datentyp haben. In diesen Fällen sollte stattdessen Add
mit dem richtigen Datentyp verwendet werden .
SQL-Anweisungen als Befehl ausführen
// 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();
}
Hinweis 1: Die für MSFT SQL Server spezifische Variation finden Sie unter SqlDbType-Aufzählung .
Hinweis 2: Die MySQL-spezifische Variante finden Sie unter MySqlDbType-Enumeration .
Best Practices - SQL-Anweisungen ausführen
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; }
}
Best Practice für die Arbeit mit ADO.NET
- Als Faustregel gilt, die Verbindung für minimale Zeit zu öffnen. Schließen Sie die Verbindung explizit, sobald Ihre Prozedur ausgeführt wurde. Dadurch wird das Verbindungsobjekt wieder in den Verbindungspool zurückgegeben. Max. Größe des Standardverbindungspools = 100. Durch das Verbindungspooling wird die Leistung der physischen Verbindung zu SQL Server verbessert. Verbindungspooling in SQL Server
- Binden Sie alle Datenbankverbindungen in einen using-Block ein, sodass sie auch im Falle einer Ausnahme immer geschlossen und entsorgt werden. Weitere Informationen zur Verwendung von Anweisungen finden Sie unter using-Anweisung (C # -Referenz)
- Rufen Sie die Verbindungszeichenfolgen nach Namen aus der Datei app.config oder web.config ab (abhängig vom Anwendungstyp).
- Dies erfordert einen Assemblyverweis auf
System.configuration
- Weitere Informationen zum Strukturieren Ihrer Konfigurationsdatei finden Sie unter Verbindungszeichenfolgen und Konfigurationsdateien
- Dies erfordert einen Assemblyverweis auf
- Verwenden Sie immer Parameter für eingehende Werte bis
- Vermeiden Sie SQL-Injektionsangriffe
- Vermeiden Sie Fehler, wenn fehlerhafter Text verwendet wird, z. B. ein einfaches Anführungszeichen. Dies ist das SQL-Äquivalent für das Escape-Zeichen oder das Starten einer Zeichenfolge (varchar / nvarchar).
- Durch die Wiederverwendung von Abfrageplänen durch den Datenbankanbieter (nicht von allen Datenbankanbietern unterstützt) wird die Effizienz erhöht
- Beim Arbeiten mit Parametern
- Typ und Größe der SQL-Parameter sind eine häufige Ursache für Fehler beim Einfügen / Aktualisieren / Auswählen
- Geben Sie Ihren SQL-Parametern sinnvolle Namen, genau wie Sie Variablen in Ihrem Code verwenden
- Geben Sie den Datenbankdatentyp der von Ihnen verwendeten Spalte an. Dadurch wird sichergestellt, dass keine falschen Parametertypen verwendet werden, die zu unerwarteten Ergebnissen führen können
- Bestätigen Sie Ihre eingehenden Parameter, bevor Sie sie an den Befehl übergeben (wie das Sprichwort sagt: " Müll rein, Müll raus "). Überprüfen Sie eingehende Werte so früh wie möglich im Stapel
- Verwenden Sie beim Zuweisen Ihrer Parameterwerte die richtigen Typen. Beispiel: Weisen Sie nicht den Zeichenfolgenwert einer DateTime zu, sondern weisen Sie dem Wert des Parameters eine tatsächliche DateTime-Instanz zu
- Geben Sie die Größe der Zeichenfolgentypparameter an. Dies liegt daran, dass SQL Server Ausführungspläne wiederverwenden kann, wenn die Parameter in Typ und Größe übereinstimmen. Verwenden Sie -1 für MAX
- Verwenden Sie nicht die Methode AddWithValue . Der Hauptgrund ist, dass es sehr leicht ist, bei Bedarf den Parametertyp oder die Genauigkeit / Skalierung anzugeben. Weitere Informationen finden Sie unter Können AddWithValue bereits eingestellt werden?
- Bei Verwendung von Datenbankverbindungen
- Öffnen Sie die Verbindung so spät wie möglich und schließen Sie sie so bald wie möglich. Dies ist eine allgemeine Richtlinie, wenn Sie mit externen Ressourcen arbeiten
- Teilen Sie niemals Datenbankverbindungsinstanzen gemeinsam (Beispiel: Ein Singleton-Host hat eine gemeinsam genutzte Instanz vom Typ
SqlConnection
). Lassen Sie Ihren Code bei Bedarf immer eine neue Datenbankverbindungsinstanz erstellen, und dann den aufrufenden Code entsorgen und "wegwerfen", wenn er fertig ist. Der Grund dafür ist- Die meisten Datenbankanbieter verfügen über eine Art Verbindungspooling, sodass das Erstellen neuer verwalteter Verbindungen kostengünstig ist
- Es beseitigt zukünftige Fehler, wenn der Code mit mehreren Threads arbeitet
Verwenden gemeinsamer Schnittstellen, um herstellerspezifische Klassen zu isolieren
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()) {
...
}
}
}
}