Ich arbeite in meinen Projekten viel mit ADO.NET. Allerdings finde ich, dass man bei ADO.NET viel zu viel Code hinschreiben muss. Das ist bei Anwendungen, die ständig irgendwelche Datenbankabfragen ausführen lästig.
Deshalb habe ich mir eine Klasse geschrieben, die häufig benötigte Datenbankoperationen kapselt. Im Zeichen von ADO.NET 2.0 natürlich providerneutral. Deshalb kann meine Database-Klasse in verbindung mit allen Datenbanksystemen verwendet werden, für die ein Managed Provider zur Verfügung steht.
Die Anwendung ist sehr einfach. Alle Methoden der Database-Klasse sind statisch. Folgende Methoden sind vorhanden:
- Query (Führt eine SQL SELECT-Anweisung aus und gibt eine DataTable zurück)
- Update (Überträgt Änderungen an einer DataTable auf die Datenbank)
- CreateParameter (Erzeugt einen Parameter für parametrisierte Abfragen)
- GetTableNameFromQuery (Ermittelt den Tabellennamen aus einer SELECT-Anweisung)
Beispiel für die Verwendung der Query-Methode:
// using System.Data.Common; NICHT VERGESSEN!
// Anbieter-Fabrik für SQL Server erzeugen
DbProviderFactory factory = DbProviderFactories.GetFactory("System.Data.SqlClient");
// Verbindungszeichenfolge
string connectionString="Data Source=SERVER;Inital Catalog=Test;Integrated Security=true";
// Parameterliste erstellen
IList<DbParameter> parameters=new List<DbParameter>;
parameters.Add(Database.CreateParameter(factory,"@categoryID",DbType.Int32,ParameterDirection.Input,32));
parameters.Add(Database.CreateParameter(factory,"@discontinued",DbType.Boolean,ParameterDirection.Input,false));
// Parametrisierte Abfrage ausführen
DataTable result=Database.Query(factory,connectionString,"SELECT * FROM Articles WHERE CategoryID=@categoryID AND Discontinued=@discontinued",parameters);
// using System.Data.Common; NICHT VERGESSEN!
// Anbieter-Fabrik für SQL Server erzeugen
DbProviderFactory factory = DbProviderFactories.GetFactory("System.Data.SqlClient");
// Verbindungszeichenfolge
string connectionString="Data Source=SERVER;Inital Catalog=Test;Integrated Security=true";
// Änderungen an der DataTable in die Datenbank schreiben
Database.Update(factory, connectionString, result);
Transaktionen sind absichtlich nicht integriert, da ich es für sinnvoller halte, Transaktionen mit System.Transactions zu machen. Hier ein Beispiel eines Updates von zwei Tabellen unter Verwendung einer System.Transactions-Transaktion:
// using System.Data.Common; NICHT VERGESSEN!
// using System.Transactions; NICHT VERGESSEN!
// Anbieter-Fabrik für SQL Server erzeugen
DbProviderFactory factory = DbProviderFactories.GetFactory("System.Data.SqlClient");
// Verbindungszeichenfolge
string connectionString="Data Source=SERVER;Inital Catalog=Test;Integrated Security=true";
// Transaktionsklammer setzen
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
{
// Änderungen an Tabelle 1 übernehmen
Database.Update(factory, connectionString, table1);
// Änderungen an Tabelle 1 übernehmen
Database.Update(factory, connectionString, table2);
// Transaktion abschließen (commit)
scope.Complete();
}
Hier ist der komplette Quellcode, der Datenzugriffsklasse:
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.Common;
namespace Rainbird.Tools.DataAccess
{
/// <summary>
/// Implementiert einfachen Datenzugriff auf Relationale Datenbanken.
/// </summary>
public class Database
{
/// <summary>
/// Speichert Änderungen an einer Tabelle in der Datenbank.
/// </summary>
/// <param name="factory">Fabrik des Datenanbieters</param>
/// <param name="connectionString">Verbindungszeichenfolge</param>
/// <param name="table">Tabelle mit Änderungen</param>
public static void Update(DbProviderFactory factory, string connectionString, DataTable table)
{
// Datenbankverbindung erzeugen
using (DbConnection connection = factory.CreateConnection())
{
// Verbindungszeichenfolge übernehmen
connection.ConnectionString = connectionString;
// SELECT-Befehl zusammensetzen
StringBuilder statement = new StringBuilder();
statement.Append("SELECT * FROM ");
statement.Append(table.TableName);
statement.Append(" WHERE 0=1");
// Datenbankbefehl erzeugen
DbCommand selectCommand = factory.CreateCommand();
selectCommand.Connection = connection;
selectCommand.CommandType = CommandType.Text;
selectCommand.CommandText = statement.ToString();
// Datenadapter erzuegen
DbDataAdapter adapter = factory.CreateDataAdapter();
adapter.SelectCommand = selectCommand;
adapter.AcceptChangesDuringUpdate = true;
// Befehlsgenerator erzeugen
DbCommandBuilder builder = factory.CreateCommandBuilder();
builder.ConflictOption = ConflictOption.CompareAllSearchableValues;
builder.DataAdapter = adapter;
// Änderungen übernehmen
adapter.Update(table);
}
}
/// <summary>
/// Führt eine Datenbankabfrage aus.
/// </summary>
/// <param name="factory">Fabrik des Datenbanbieters</param>
/// <param name="connectionString">Verbindungszeichenfolge zur Datenbank</param>
/// <param name="query">SQL-SELECT-Abfrage</param>
/// <param name="parameters">Paramaterliste (Optional)</param>
/// <returns>Tabelle mit Abfrageergebnissen</returns>
public static DataTable Query(DbProviderFactory factory, string connectionString, string query, IList<DbParameter> parameters)
{
// Tabellenname ermitteln
string tableName = GetTableNameFromQuery(query);
// Tabelle erzeugen
DataTable table = new DataTable(tableName);
// Datenbankverbindung erzeugen
using (DbConnection connection = factory.CreateConnection())
{
// Verbindungszeichenfolge übernehmen
connection.ConnectionString = connectionString;
// Datenbankbefehl erzeugen
DbCommand command = factory.CreateCommand();
command.Connection = connection;
command.CommandType = CommandType.Text;
command.CommandText = query;
// Wenn Parameter angegeben wurden ...
if (parameters != null)
{
// Alle Parameter durchlaufen
foreach (DbParameter parameter in parameters)
{
// Parameter zufügen
command.Parameters.Add(parameter);
}
}
// Datenadapter erzeugen
DbDataAdapter adapter = factory.CreateDataAdapter();
adapter.SelectCommand = command;
// Abfrage ausführen
adapter.Fill(table);
}
// Tabelle zurückgeben
return table;
}
/// <summary>
/// Ermittelt den Tabellennamen für eine DataTable aus einer SQL-Abfrage.
/// </summary>
/// <param name="query">SQL-Abfrage</param>
/// <returns>Tabellenname</returns>
public static string GetTableNameFromQuery(string query)
{
// SQL-Abfrage zerlegen
string[] parts = query.Split(' ');
// Alle Teile durchlaufen
for (int i = 0; i < parts.Length; i++)
{
// Wenn der aktuelle Teil "FROM" ist ...
if (parts[i].ToLower() == "from")
{
// Tabellenname lesen und zurückgeben
return parts[i + 1].Split(',')[0];
}
}
// "Table" zurückgeben
return "Table";
}
/// <summary>
/// Erzeugt einen Parameter für eine Datenbankabfrage.
/// </summary>
/// <param name="factory">Fabrik des Datenbanbieters</param>
/// <param name="name">Name des Parameters</param>
/// <param name="type">Datentyp</param>
/// <param name="size">Größe</param>
/// <param name="direction">Richtung (Eingabe- oder Ausgabeparameter)</param>
/// <param name="value">Wert</param>
/// <returns>Fertig konfigurierter Parameter</returns>
public static DbParameter CreateParameter(DbProviderFactory factory, string name,DbType type,int size,ParameterDirection direction,object value)
{
// Neuen Parameter erzeugen
DbParameter parameter=factory.CreateParameter();
parameter.ParameterName = name;
parameter.DbType = type;
parameter.Size = size;
parameter.Direction = direction;
parameter.Value = value;
// Parameter zurückgeben
return parameter;
}
/// <summary>
/// Erzeugt einen Parameter für eine Datenbankabfrage.
/// </summary>
/// <param name="factory">Fabrik des Datenbanbieters</param>
/// <param name="name">Name des Parameters</param>
/// <param name="type">Datentyp</param>
/// <param name="direction">Richtung (Eingabe- oder Ausgabeparameter)</param>
/// <param name="value">Wert</param>
/// <returns>Fertig konfigurierter Parameter</returns>
public static DbParameter CreateParameter(DbProviderFactory factory, string name, DbType type, ParameterDirection direction, object value)
{
// An andere Überladung delegieren
return CreateParameter(factory, name, type, 0, direction, value);
}
/// <summary>
/// Erzeugt einen Parameter für eine Datenbankabfrage.
/// </summary>
/// <param name="factory">Fabrik des Datenbanbieters</param>
/// <param name="name">Name des Parameters</param>
/// <param name="type">Datentyp</param>
/// <param name="direction">Richtung (Eingabe- oder Ausgabeparameter)</param>
/// <returns>Fertig konfigurierter Parameter</returns>
public static DbParameter CreateParameter(DbProviderFactory factory, string name, DbType type, ParameterDirection direction)
{
// An andere Überladung delegieren
return CreateParameter(factory, name, type, 0, direction, DBNull.Value);
}
/// <summary>
/// Erzeugt einen Parameter für eine Datenbankabfrage.
/// </summary>
/// <param name="factory">Fabrik des Datenbanbieters</param>
/// <param name="name">Name des Parameters</param>
/// <param name="type">Datentyp</param>
/// <param name="size">Größe</param>
/// <param name="direction">Richtung (Eingabe- oder Ausgabeparameter)</param>
/// <returns>Fertig konfigurierter Parameter</returns>
public static DbParameter CreateParameter(DbProviderFactory factory, string name, DbType type, int size, ParameterDirection direction)
{
// An andere Überladung delegieren
return CreateParameter(factory, name, type, size, direction, DBNull.Value);
}
}
}
Außerdem befindet sich im Anhang eine fertige Visual Studio 2005 Projektmappe zum download.
Schlagwörter: ADO.NET, Provider, DataTable, DataSet, DataAdapter, CommandBuilder, Datenzugriff, DAL