NET 2: ADO.NET Thema Lektion 8 und 9

Die Seite wird erstellt Niko-Veit Berndt
 
WEITER LESEN
NET 2: ADO.NET Thema Lektion 8 und 9
.NET 2: ADO.NET

                  Thema Lektion
                  8 und 9
NET 2: ADO.NET Thema Lektion 8 und 9
.NET 2: ADO.NET

.NET Framework  .NET Core?!

Es wird versucht, jeweils darauf hinzuweisen, falls Unterschiede bekannt sind…
NET 2: ADO.NET Thema Lektion 8 und 9
ADO.NET
Themen zu ADO.NET:
1. ADO.NET Basics
2. Data Provider

Nächste Woche:
3. DataReader (Anwendung)
4. DataSet
5. LINQ to SQL
6. Entity Framework
7. Informationssicherheit
NET 2: ADO.NET Thema Lektion 8 und 9
1. ADO.NET Basics

                                                                 https://docs.microsoft.com/en-us/dotnet/api/system.data?view=net-6.0

https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/
NET 2: ADO.NET Thema Lektion 8 und 9
1. ADO.NET Basics
Was ist ADO.NET?
•   Daten-Zugriffs-Technology/Services, direkteste Methode des Datenzugriffs
•   Eine "Evolution" der ActiveX Data Objects (ADO) Technologie
•   Zugriff auf relationale, XML und andere Datenstrukturen
•   .NET Framework: Teilmenge der Klassen in System.Data
•   .NET Core: NuGet-Package System.Data.SqlClient (SQL Server),
    mit Ausnahme von Datasets und verwandten Typen (2019)
NET 2: ADO.NET Thema Lektion 8 und 9
1. ADO.NET Basics
Grunsätzliche Verwendung
von ADO.NET:
1. DataReader
   Abrufen eines read-only,
   forward-only stream von
   Daten (direkter Pfeil ganz recht)
2. DataSet:
   Sammlung von DataTables, bestehend aus Zeilen und Spalten, Primärschlüssel,
   Fremdschlüssel, Constraints, etc.
3. LINQ to SQL
   Abfragen gegen ein Objekt-
   modell, das auf relationale
   DBMS abgebildet wird, ohne
   intermediäres, konzeptionelles
   Modell.
4. Entity Framework
   Object-relational
   mapper (O/RM)
NET 2: ADO.NET Thema Lektion 8 und 9
1. ADO.NET Basics
Data Provider
Verbinden mit einer "Datenbank", Ausführen von Befehlen und Abrufen von
Ergebnissen. In .NET Framework enthalten sind Data Provider für:
1.   SQL Server
2.   ODBC
3.   OLE DB                       Da verschiedene Datenspeichertechnologien
                                  unterschiedliche Fähigkeiten haben können, kann
4.   ORACLE
                                  nicht jeder Provider jede mögliche Schnittstelle
5.   EntityClient                 implementieren.
6.   SQL Server Compact

.NET Core unterstützt den SQL
Server, ODBC und OleDB.
Es hat weitere NuGet-Packages
für andere DBs (Umfang
unklar).
Der EntityClient wird durch das
EntityFramework verwendet und
basiert auf anderen Providern.
SQL Server Compact ist
deprecated (2013, Support bis
2021, nur Framework).
NET 2: ADO.NET Thema Lektion 8 und 9
1. ADO.NET Basics

                    NuGet-Package für SqlClient
                          in .NET Core
                        (dieses ist nur für
                        den SQL Server)
NET 2: ADO.NET Thema Lektion 8 und 9
1. ADO.NET Basics
Data Provider in .NET Core (NuGet-Package)

                                                NuGet-Package für SqlClient
                                                         in .NET Core
                                             (dieses ist nur für den SQL Server)
1. ADO.NET Basics
Data Provider Oracle (NuGet-Package)
2. Data Provider: Hauptkomponenten
4 Hauptelemente eines Data-Provider (7 weitere folgen anschliessend):
1. Connection  Stellt eine Verbindung zu einer bestimmten Datenquelle her.
2. Command     Führt einen Befehl gegen eine Datenquelle aus. Exponiert
               Parameter und kann in einer Transaktion ausgeführt werden.
3. DataReader Liest einen schreibgeschützten Datenstrom aus einer
               Datenquelle.
4. DataAdapter Liest eine Menge von Tabellen, füllt diese in ein DataSet und
               speichert Änderungen.
2. Data Provider: Hauptkomponenten
4 Hauptelemente eines Data-Provider (7 weitere folgen später):
1. Connection  Stellt eine Verbindung zu einer bestimmten Datenquelle her.
2. Command     Führt einen Befehl gegen eine Datenquelle aus. Exponiert
               Parameter und kann in einer Transaktion ausgeführt werden.
3. DataReader Liest einen schreibgeschützten Datenstrom aus einer
               Datenquelle.
4. DataAdapter Liest eine Menge von Tabellen, füllt diese in ein DataSet und
               speichert Änderungen.
2. Data Provider: Connection
Connection (implementiert IDbConnection-Interface)
Jeder Data-Provider, der in .NET inbegriffen ist, hat ein spezifisches
DbConnection-Objekt, z.B.:
 •   SQL Server: SqlConnection Klasse (System.Data.SqlClient)
 •   OLE DB: OleDbConnection Klasse (System.Data.OleDB)
 •   ODBC: OdbcConnection Klasse (System.Data.Odbc)
 •   Oracle: OracleConnection Klasse (Framework: System.Data.OracleClient/
     Core: Oracle.DataAccess.Client)
     public SqlConnection ();
     public SqlConnection (string connectionString);
     public SqlConnection (string connectionString, System.Data.SqlClient.SqlCredential cred);

     using System.Data.SqlClient;

     SqlConnection connection = new SqlConnection(
         "Data Source=(local);Initial Catalog=DAB1;Integrated Security=true");

     connection.Open();
     // do work here
     connection.Close();
2. Data Provider: Connection
Wird eine Connection nicht geschlossen, werden:
• wertvolle Ressourcen verschwendet und
• allenfalls eine Transaktion nicht geschlossen (Locks bleiben bestehen,
  andere User können nicht arbeiten).
Besser:
    using System.Data.SqlClient;

    using (SqlConnection connection = new SqlConnection(
        " Data Source=(local);Initial Catalog=DAB1;Integrated Security=true";))
    {
        // The connection must still be opened explicitly
        connection.Open();

        // Do work here...
    }
    // Connection is closed automatically
2. Data Provider: Connection Pool
Öffnen einer DB-Connection kann sehr zeitaufwendig sein
Idee: Die meisten Verbindungen haben nur eine oder wenige
Konfigurationen. Der Pooler lässt aktive Verbindungen am Leben und
verwendet diese wieder.
 Ein Connection Pool ist ein Cache von Datenbankverbindungen für
  SQL Server, OleDB und Oracle.
ODBC hat eigenen Connection Pool.
2. Data Provider: Hauptkomponenten
4 Hauptelemente von Data Providern (7 weitere folgen später):
1. Connection  Stellt eine Verbindung zu einer bestimmten Datenquelle her.
2. Command     Führt einen Befehl gegen eine Datenquelle aus. Exponiert
               Parameter und kann in einer Transaktion ausgeführt werden.
3. DataReader Liest einen schreibgeschützten Datenstrom aus einer
               Datenquelle.
4. DataAdapter Füllt ein DataSet und speichert Änderungen.

   Command verwendet das
    Connection-Objekt zur
  Herstellung der Verbindung
2. Data Provider: Command
• Command (implementiert IDbCommand-Interface).
• Führt einen Befehl gegen eine Datenquelle aus.
• Exponiert Parameter und kann im Rahmen einer Transaktion aus einer
  Verbindung heraus ausgeführt werden. Die (abstrakte) Basisklasse für alle
  Kommandoobjekte ist die Klasse DbCommand.

Jeder Data-Provider hat eine eigene Command-Klasse:
1.   SqlCommand Klasse (Transact-SQL)
2.   OracleCommand Klasse
3.   OdbcCommand Klasse
4.   OleDbCommand Klasse
2. Data Provider: Command
Jedes dieser Command-Objekte hat mehrere Methoden um einen bestimmten Typ
eines Kommandos auszuführen:
1. ExecuteReader / ExecuteXMLReader
   Gibt ein DataReader-Objekt (3. Hauptkomponente des Data-Provider, Details
   folgen) zurück. Er bietet ungepufferten Stream, z.B. zum Lesen aller Daten
   einer Tabelle.
   Der XmlReader ist nur für das SqlCommand-Objekt verfügbar.
2. ExecuteScalar
   Gibt einzelnen Wert zurück, z.B. zum Bestimmen der Anzahl Datensätze einer
   Tabelle.
3. ExecuteNonQuery
   Führt einen Befehl aus, der keine Daten zurückgibt, z.B. Einfügen, Löschen
   oder Ändern eines Datensatzes, oder eine Stored Procedure.
2. Data Provider: Command
Jedes Command-Objekt legt mit dem CommandType fest, wie der Command
interpretiert werden muss:
1. Text (Default)
   Ein SQL-Befehl (mit oder ohne Parameter).
2. StoredProcedure
   Der Name der Stored Procedure. Über die Parameter eines Befehls kann auf
   Ein- und Ausgabeparameter zugegriffen werden.
3. TableDirect
   Nur mit OleDbCommand, alle Datensätze einer Tabelle.
2. Data Provider: Command Beispiel

  public SqlCommand ();
  public SqlCommand (string cmdText);
  public SqlCommand (string cmdText, System.Data.SqlClient.SqlConnection connection);
  public SqlCommand (string cmdText, System.Data.SqlClient.SqlConnection connection,
      System.Data.SqlClient.SqlTransaction transaction);
                                                              Der CommandType
  using (SqlConnection connection =                           ist hier Text (Default).
     new SqlConnection("Data Source=(local);Initial Catalog=DAB1;Integrated Security=true"))
  {
     // Create the command, the SQL-Statement and set its properties and parameters.
     using (SqlCommand command = new SqlCommand(
        "INSERT INTO L (LNR, LName, Status, Stadt) VALUES (@LNR, @LName, @Status, @Stadt)",
        connection))
     {
        command.CommandType = CommandType.Text;
        command.Parameters.AddWithValue("@LNR", "ZHAW");
        command.Parameters.AddWithValue("@LName", "Zürcher FH");
        command.Parameters.AddWithValue("@Status", 4);
        command.Parameters.AddWithValue("@Stadt", "Winterthur");
        // Open the connection and execute the reader.
        connection.Open();
        int rowsAffected = command.ExecuteNonQuery();          Parameter verhindern
        connection.Close();                                    SQL-Injection.
     }
  }       ExecuteNonQuery: Führt
         einen Befehl aus, der keine
         Daten zurückgibt.
2. Data Provider: Hauptkomponenten
4 Hauptelemente von Data Providern (7 weitere folgen später):
1. Connection  Stellt eine Verbindung zu einer bestimmten Datenquelle her.
2. Command     Führt einen Befehl gegen eine Datenquelle aus. Exponiert
               Parameter und kann in einer Transaktion ausgeführt werden.
3. DataReader Liest einen schreibgeschützten Datenstrom aus einer
               Datenquelle.
4. DataAdapter Füllt ein DataSet und speichert Änderungen.

 Wird durch ein
Command-Objekt
    erzeugt
2. Data Provider: DataReader
• Stellt einen ungepufferten Datenstrom zur Verfügung.
• Gute Wahl für grosse Datenmengen, da Daten nicht zwischengespeichert
  werden. Ausschliesslich vorwärts lesen möglich.
• Um Daten mit einem DataReader zu lesen, erstellen Sie eine Instanz des
  Command-Objekts und dann einen DataReader, indem Sie
  Command.ExecuteReader aufrufen (kein Konstruktor).
Jeder Data Provider hat eine eigenes DataReader Klasse:
1. SqlDataReader Klasse
2. OracleDataReader Klasse
3. OdbcDataReader Klasse
4. OleDbDataReader Klasse
ConnectionPool:
Die Verbindung wird ausschliesslich verwendet. Immer mit Close() schliessen!
    public System.Data.SqlClient.SqlDataReader ExecuteReader ();
    public System.Data.SqlClient.SqlDataReader ExecuteReader (System.Data.CommandBehavior
        behavior);

    public System.Xml.XmlReader ExecuteXmlReader ();
2. Data Provider: DataReader Beispiel
  using (SqlConnection connection = new SqlConnection(connectionString)) {
      // Create the command and set its properties.
      SqlCommand command = new SqlCommand();
      command.Connection = connection;
                                                                  DataReader zusammen mit
      command.CommandText = "SalesByCategory";
      command.CommandType = CommandType.StoredProcedure;          StoredProcedure verwendet.

      // Add one input parameter and set its properties.
      SqlParameter parameter = new SqlParameter();
      parameter.ParameterName = "@CategoryName";
      parameter.SqlDbType = SqlDbType.NVarChar;
      parameter.Direction = ParameterDirection.Input;
      parameter.Value = "Category";

      // 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]);
              }
          }                              Liest eine Row des Resultats ein.
      }
  }
                 DataReader wird geschlossen
                 (auch im Fehlerfall).
2. Data Provider: Hauptkomponenten
 4 Hauptelemente von Data Providern (7 weitere folgen später):
 1. Connection  Stellt eine Verbindung zu einer bestimmten Datenquelle her.
 2. Command     Führt einen Befehl gegen eine Datenquelle aus. Exponiert
                Parameter und kann in einer Transaktion ausgeführt werden.
 3. DataReader Liest einen schreibgeschützten Datenstrom aus einer
                Datenquelle.
 4. DataAdapter Füllt ein DataSet und speichert Änderungen.

Verwendet vier
 Command-
   Objekte
2. Data Provider: DataAdapter
• Hat 4 Properties vom Typ Command:
       •   SelectCommand: Daten suchen
       •   InsertCommand: Daten einfügen
       •   UpdateCommand: Daten ändern
       •   DeleteCommand: Daten löschen
• Fill(): Daten lesen (gemäss SelectCommand)
       •   Liest Daten (Mengen von Rows) aus einer Datenquelle und speichert diese im
           DataSet (Sammlung von Tabellen/Relationen).

• Update(): Daten ändern (gemäss Insert-, Update- und DeleteCommand)
       •   Speichert Änderungen am DataSet in die Datenquelle.

Jeder Data Provider hat eine eigene DataAdapter Klasse:
1.   SqlDataAdapter Klasse
2.   OracleDataAdapter Klasse
3.   OdbcDataAdapter Klasse
4.   OleDbDataAdapter Klasse
2. Data Provider: DataAdapter Fill()
Beispiel: Fügt Zeilen ins DataSet hinzu (gemäss SelectCommand):
    public SqlDataAdapter ();
    public SqlDataAdapter (System.Data.SqlClient.SqlCommand selectCommand);
    public SqlDataAdapter (string selectCommandText, System.Data.SqlClient.SqlConnection
        selectConnection);
                                                                 Erzeugt den DataAdapter.
    // Create the data adapter and the select command.
    SqlDataAdapter customerAdapter = new SqlDataAdapter();
    customerAdapter.SelectCommand = new SQLCommand("SELECT * FROM dbo.Customers", connection);

    // Create the data set (holding the result).          Verknüpft den DataAdapter mit
    DataSet customerOrders = new DataSet();               einem Command-Objekt.

    // Read the data from the database and output each record.
    customerAdapter.Fill(customerOrders, "Customers");

    foreach (DataRow customerRow in customerOrders.Tables["Customers"].Rows)
    {
        Console.WriteLine(customerRow["CustomerID"]);
    }

• Wird (wann, wo) hier auf dem DB-Server eine Transaktion verwendet?
• Wenn ja, was ist der Isolations-Level der Transaktion?
• Wie verhält es sich beim DataReader?
2. Data Provider: DataAdapter Update()
Für jede Zeile in der Tabelle bestimmt die Methode Update die Art der Änderung und
führt die korrespondierende command-Vorlage (Insert, Update oder Delete) aus.
    using (SqlConnection connection = new SqlConnection(connectionString)) {
        // Create the data adapter and the select command.
        SqlDataAdapter categoryAdpater = new SqlDataAdapter(      Adapter erstellen
             "SELECT CategoryID, CategoryName FROM Categories", connection);
        // Create the update command.
        categoryAdpater.UpdateCommand = new SqlCommand(         Update-Command erstellen
             "UPDATE Categories SET CategoryName = @CategoryName " +
             "WHERE CategoryID = @CategoryID", connection);
        // Add the parameters for the UpdateCommand.
        categoryAdpater.UpdateCommand.Parameters.Add(       Parameter erstellen
             "@CategoryName", SqlDbType.NVarChar, 15, "CategoryName");
        SqlParameter parameter = categoryAdpater.UpdateCommand.Parameters.Add(
             "@CategoryID", SqlDbType.Int);
        parameter.SourceColumn = "CategoryID";         Parameter befüllen
        parameter.SourceVersion = DataRowVersion.Original;

        // Load the data from the DB into the table of the dataset
        DataTable categoryTable = new DataTable();
        categoryAdpater.Fill(categoryTable);
        // Change the value of the attribute CategoryName of the first row (in memory)
        DataRow categoryRow = categoryTable.Rows[0];
        categoryRow["CategoryName"] = "New Beverages";

        // Propagate all changes to the DB
                                                  Alle geänderten Daten-
        categoryAdpater.Update(categoryTable);    sätze in DB speichern
    }
2. Data Provider: Weitere Elemente
4 Hauptelemente von Data Providern (7 weitere folgen später):
1. Connection  Stellt eine Verbindung zu einer bestimmten Datenquelle her.
2. Command     Führt einen Befehl gegen eine Datenquelle aus. Exponiert
               Parameter und kann in einer Transaktion ausgeführt werden.
3. DataReader Liest einen schreibgeschützten Datenstrom aus einer
               Datenquelle.
4. DataAdapter Füllt ein DataSet und speichert Änderungen.
2. Data Provider: Weitere Elemente
7 weitere Elemente des Data Provider:
1. Transaction
   Transaktionssteuerung der Befehle.
2. CommandBuilder
   Erzeugt automatisch Befehlseigenschaften eines DataAdapters.
3. ConnectionStringBuilder
   Erstellt und Verwaltet ConnectionStrings
4. Parameter
   Definiert Eingabe-, Ausgabe- und Rückgabewertparameter für Befehle und
   Stored Procedures.
5. DbExecption
   Wird zurückgegeben, wenn ein Fehler in der Datenquelle aufgetreten ist.
6. Error
   Enthält die Informationen aus einer Warnung oder einem Fehler, die von
   einer Datenquelle zurückgegeben werden.
7. ClientPermission
   Zugriff auf Sicherheitsattribute.
2. Data Provider: Weitere Elemente
7 weitere Elemente des Data Provider:
1. Transaction
   Transaktionssteuerung der Befehle.
2. CommandBuilder
   Erzeugt automatisch Befehlseigenschaften eines DataAdapters.
3. ConnectionStringBuilder
   Erstellt und Verwaltet ConnectionStrings
4. Parameter
   Definiert Eingabe-, Ausgabe- und Rückgabewertparameter für Befehle und
   Stored Procedures.
5. DbExecption
   Wird zurückgegeben, wenn ein Fehler in der Datenquelle aufgetreten ist.
6. Error
   Enthält die Informationen aus einer Warnung oder einem Fehler, die von
   einer Datenquelle zurückgegeben werden.
7. ClientPermission
   Zugriff auf Sicherheitsattribute.
2. Data Provider: Transaction
• Eine Transaktion besteht aus einem einzelnen Befehl oder einer Gruppe von
  Befehlen, die als Ganzes (ACID) ausgeführt werden.
• Wenn es mehrere Tabellen in derselben DB / Server betrifft, dann bieten
  Stored Procedures bessere Performance.
• Lokale Transaktion: Single-phase Commit - Transaktion direkt von der DB
  verarbeitet. Die Transaktion wird von der DB «kontrolliert».
• Verteilte Transaktion: Two-phase Commit - Transaktionen, die verschiedene
  Ressourcenmanager betreffen, wie z.B. eine Transaktion mit SQL Server und
  Oracle.
• Transaktionen, können die Parallelität verringern, wenn Sperren lange gehalten
  werden. Halten Sie daher Transaktionen so kurz wie möglich.

• Was passiert, wenn eine Sperre nicht freigegeben wird?
2. Data Provider: Local Transaction
Jeder Data Provider hat eine eigene Transaction Klasse:
1.   SqlTransaction Klasse
2.   OracleTransaction Klasse
3.   OdbcTransaction Klasse
4.   OleDbTransaction Klasse

     public System.Data.OleDb.OleDbTransaction BeginTransaction ();
     public System.Data.OleDb.OleDbTransaction BeginTransaction (System.Data.IsolationLevel
         isolationLevel);

     // Start a local transaction.
     SqlTransaction sqlTransaction = connection.BeginTransaction();
     // Enlist a command in the current transaction.
     SqlCommand command = connection.CreateCommand();          Start der Transaktion.
     command.Transaction = sqlTransaction;
     // execute some commands...
     ...
     // Commit the transaction.
     sqlTransaction.Commit();

                                 Ende der Transaktion.
2. Data Provider: Local Transaction
using (SqlConnection connection = new SqlConnection(connectionString)) {
    connection.Open();
    // Start a local transaction.
    SqlTransaction sqlTransaction = connection.BeginTransaction();
    // Enlist a command in the current transaction.
    SqlCommand command = connection.CreateCommand();
    command.Transaction = sqlTransaction;
    try {                                           Die SQL-Statements des command-Objekts
         // Execute two separate commands.          warden innerhalb dieser Transaktion durchgeführt.
         command.CommandText = "INSERT INTO Production.ScrapReason (Name) VALUES ('Wrong size')";
         command.ExecuteNonQuery();
         command.CommandText = "INSERT INTO Production.ScrapReason (Name) VALUES ('Wrong color')";
         command.ExecuteNonQuery();
         // Commit the transaction.
         sqlTransaction.Commit();              Transaktion wird geschlossen (Locks freigegeben).
         Console.WriteLine("Both records were written to database.");
    }
    catch (Exception ex) {
         // Handle the exception if the transaction fails to commit.
         Console.WriteLine(ex.Message);
         try {
             // Attempt to roll back the transaction.
             sqlTransaction.Rollback();
         }                                     Transaktion wird zurückgesetzt (Locks freigegeben).
         catch (Exception exRollback) {
             // Throws an InvalidOperationException if the connection is closed or
             // the transaction has already been rolled back on the server.
             Console.WriteLine(exRollback.Message);
         }
    }
}
2. Data Provider: Local Transaction
Anstelle der Klasse Transaction kann auch die Klasse TransactionScope
(System.Transactions) verwendet werden (empfohlen durch MS):

    public TransactionScope ();
    public TransactionScope (System.Transactions.Transaction transaction);
    Und viele mehr...

    // Create the TransactionScope to execute the commands, guaranteeing
    // that all commands can commit or roll back as a single unit of work.
    using (TransactionScope transactionScope = new TransactionScope()) {
        using (SqlConnection connection = new SqlConnection(connectString)) {
             // Opening the connection automatically enlists it in the TransactionScope
             connection.Open();
             ...
             // Create the SqlCommand object.
             SqlCommand command = new SqlCommand(commandText, connection);
             ...
        }
        // The Complete method commits the transaction. If an exception has been thrown,
        // complete is not called and the transaction is rolled back.
          transactionScope.Complete();
    }
                                      Transaktion wird geschlossen
                                      (Locks freigegeben).
2. Data Provider: Local Transaction
 // Create the TransactionScope to execute the commands, guaranteeing
 // that both commands can commit or roll back as a single unit of work.
 using (TransactionScope scope = new TransactionScope()) {
     using (SqlConnection connection = new SqlConnection(connectString))    {
          // Opening the connection automatically enlists it in the
          connection.Open();
          // Create the SqlCommand object and execute the first command.
          SqlCommand command = connection.CreateCommand();
          command.CommandText = "INSERT INTO Production.ScrapReason(Name)   VALUES('Wrong size')";
          command.ExecuteNonQuery();
          command.CommandText = "INSERT INTO Production.ScrapReason(Name)   VALUES('Wrong color')";
          command.ExecuteNonQuery();
     }
     // The Complete method commits the transaction. If an exception has    been thrown,
     // Complete is not called and the transaction is rolled back.
     scope.Complete();
 }

• Rollback ist nicht notwendig, wird automatisch ausgelöst, falls Fehler
  auftritt.
2. Data Provider: Distributed Transaction
•   Sollen mehrere unabhängig DBMS eine gemeinsame Transaktion
    durchführen spricht man von einer verteilten Transaktion.
•   Der Two Phase Commit (Zwei-Phasen-Commit) regelt die
    Synchronisation der Transaktionen über mehrere DBMS (cross-
    database) hinweg (nicht verwechseln mit Zwei-Phasen-Sperr-
    Protokoll).
•   Diese Synchronisation ist Aufwändig und kann Ressourcen lange Zeit
    sperren…
•   Verteilte Transaktionen sollten nach Möglichkeit NICHT verwendet
    werden -> andere Lösungen suchen.
2. Data Provider: Distributed Transaction
                 2-Phasen-Commit-Protokoll im Normalbetrieb

                     Client       Transaction
                                   Manager      DBMS 1               DBMS 2

                                                                                            Wiederherstellbarkeit muss
   1. Phase Commit

                                                          Prepared                             Sichergestellt werden:
                                                    Log     Satz                           Log-Daten und Prepared-Satz
                                                                                            in Log-Datei ausschreiben.
                                                                                          Anschliessend Ready-Nachricht
                                                                         Log   Prepared               senden.
                                                                                 Satz

                              Commit                                                      Transaction Manager schreibt
                               Satz Log                                                     Commit-Satz in Log-Datei.
   2. Phase Commit

                                                    Log Commit
                                                         Satz                             Commit-Satz wird in Log-Datei
                                                                                           geschrieben, Sperren werden
                                                                                           frei gegeben. Anschliessend
                                                                         Log Commit
                                                                              Satz            ACK-Nachricht senden.
                                Ende
                                Satz Log
2. Data Provider: Distributed Transaction
Fehler: Wir betrachten als Beispiel den (unerwarteten) Neustart des
DBMS 2 (siehe vorangehende Folie).
4 mögliche Fälle für abgebrochene Transaktionen des DBMS (nicht
Transaktions-Manager):
1.   Commit in der 2. Phase erfolgt: Commit-Satz im Log von DBMS2.
     Redo-Recovery um Änderungen zu wiederholen, die noch nicht in die
     physische Datenbank gelangten.
2.   Abbruch in der 2. Phase durch Koordinator: Abort-Satz im Log von DBMS2.
     Undo-Recovery um Änderungen zurückzunehmen, die bereits in die
     physische Datenbank gelangten.
3.   Erst 1. Phase erfolgreich abgeschlossen: Prepared-Satz im Log.
     Globales Commit-Ergebnis beim Manager/Koordinator nachfragen und
     Transaktion entsprechend abschliessen.
4.   Abbruch in der 1. Phase: Kein Commit-, Abort- oder Prepared-Satz im Log.
     Transaktion abbrechen (Undo-Recovery), da Commit-Protokoll noch nicht
     begonnen wurde.
2. Data Provider: Distributed Transaction
Technische Grundlage für verteilte Transaktionen im C# und SQL Server
Umfeld:
•   X/Open XA (kurz XA, abgeleitet von eXtended Architecture): Von The
    Open Group (> 600 Mitglieder) 1991 spezifizierter Informatik-
    Standard für Distributed Transaction Processing (nicht nur für DBMS).
•   Der Distributed Transaction Coordinator (MS DTC), ist ein
    Systemdienst auf Windows Betriebssystemen, zur Koordination
    atomarer Operationen. Er implementiert den XA Standard.
•   Der SQL Server und C# benötigen für verteilte Transaktionen den
    MS DTC.
2. Data Provider: Distributed Transaction
Wie muss MS DTC und SQL Server für verteilte Transaktionen
eingerichtet werden?

1. MS DTC muss mittels Component Services Anwendung
   (Komponentendienste, comexp.msc) konfiguriert werden (Properties).
2. Data Provider: Distributed Transaction

2. In der Standardeinstellung führt ein nicht schwerwiegender Fehler, der
   durch eine Anweisung innerhalb einer Transaktion ausgelöst wird,
   nicht automatisch zu einem Rollback (erst ab fatal = severity 19 and
   above).
   Diese Einstellung sollte auf ON (je DB) gesetzt werden:
    SET XACT_ABORT { ON | OFF }

    Es lohnt sich auch für nicht verteilte Transaktionen scharf zu
    überlegen, ob XACT_ABORT aktiviert sein sollte.

   Ein Foreign-Key-Fehler hat z.B. severity 16. Bei OFF würde die
   Transaktion in diesem Fall nicht abgebrochen, sondern zur nächsten
   Anweisung übergehen.
2. Data Provider: Distributed Transaction
NUN sind zwei Anwendungsfälle möglich:
1. Verteilte Transaktion auf dem SQL Server
2. Verteilte Transaktion in C#
2. Data Provider: Distributed Transaction
1. Fall: Verteilte Transaktion auf dem SQL Server
• Auf jedem Server muss der MS DTC aktiviert sein.
• Die SQL Server müssen als Linked Server beim SQL Server des
  Transactions Managers eingetragen sein.
• Die Transaktion muss in T-SQL als verteilte Transaktion gekennzeichnet
  werden:
                                                                                           Resource
    BEGIN DISTRIBUTED { TRAN | TRANSACTION }                                               Manager
        [ transaction_name | @tran_name_variable ]                 Transaction
                                                                    Manager

                                                                                  MS DTC
                                                                                             SQL
• Es können auch andere DBMS                                                                Server
                                                                                            Local
  eingebunden werden, die                                                                   Trans.

                                                                         MS DTC
  XA-Compliant sind.                                            SQL
                                                               Server
                                                     Client
• Aus Sicht des C#-Data Providers                              Local
                                                               Trans.

                                                                                  MS DTC
  ist es eine lokale Transaktion.                                                            SQL
                                                                                            Server
                                                              Resource
• Funktioniert auch für gespiegelt                            Manager                       Local
                                                                                            Trans.
  SQL Server Datenbanken                                       Commits or rolls            Resource
  (Allways-on Feature)                                          back via 2PC               Manager
2. Data Provider: Distributed Transaction
2. Fall: Verteilte Transaktion in C#
•   Auch verteilte Transaktionen werden über die API im Namensraum
    System.Transactions verwaltet: TransactionScope (empfohlene
    Methode)
•   TransactionScope verwendet den Lightweight Transaction Manager
    (LTM), erst wenn eine verteilte Transaktion "entsteht" wird automatisch
    auf den Distributed Transaction Coordinator (MS DTC) gewechselt.
    → Eine Lightweigt Transaction ist eine lokale Transaktion, die bei
    Bedarf (sobald eine Connection zu einem anderen Server hergestellt
    wird) zu einer verteilten Transaktion wird.
•   Funktioniert auch mit der Transaction-Klasse. Sobald ein Command in
    die Transaktion aufgenommen wird, die einen anderen Server
    verwendet (command.Transaction = sqlTransaction;).
2. Data Provider: Distributed Transaction
// Create the TransactionScope to execute the commands, guaranteeing
// that both commands can commit or roll back as a single unit of work.
using (TransactionScope scope = new TransactionScope()) {
    using (SqlConnection connection1 = new SqlConnection(connectString1)) {
         // Opening the connection automatically enlists it in the
         // TransactionScope as a lightweight transaction.
         connection1.Open();
         // Create the SqlCommand object and execute the first command.
         SqlCommand command1 = new SqlCommand(commandText1, connection1);
         returnValue = command1.ExecuteNonQuery();
         writer.WriteLine("Rows to be affected by command1: {0}", returnValue);
         // If you get here, this means that command1 succeeded. By nesting
         // the using block for connection2 inside that of connection1, you
         // conserve server and network resources as connection2 is opened
         // only when there is a chance that the transaction can commit.
         using (SqlConnection connection2 = new SqlConnection(connectString2)) {
             // The transaction is escalated to a full distributed transaction when
             // connection2 is opened.
             connection2.Open();
             // Execute the second command in the second database.
             SqlCommand command2 = new SqlCommand(commandText2, connection2);
             returnValue = command2.ExecuteNonQuery();
             writer.WriteLine("Rows to be affected by command2: {0}", returnValue);
         }
    }
    // The Complete method commits the transaction. If an exception has been thrown,
    // Complete is not called and the transaction is rolled back.
    scope.Complete();
}
2. Data Provider: Transaction
Transaktionen sind ein absolut zentrales Element in der Verarbeitung von Daten.
Ein gutes Verständnis der Zusammenhänge ist enorm wichtig.
Aufgrund der grossen Bedeutung, gibt es noch viele weitere Aspekte (die wir
nicht mehr betrachten), z.B.:
• Optimistic Concurrency
• Isolation Level
• Automatisches (Default) / Manuelles Enlisting von Commands in Transaktionen
• TransactionException Klasse
• TransactionInformation Klasse
• …
2. Data Provider: Weitere Elemente
7 weitere Elemente des Data Provider:
1. Transaction
   Transaktionssteuerung der Befehle.
2. CommandBuilder
   Erzeugt automatisch Befehlseigenschaften eines DataAdapters.
3. ConnectionStringBuilder
   Erstellt und Verwaltet ConnectionStrings
4. Parameter
   Definiert Eingabe-, Ausgabe- und Rückgabewertparameter für Befehle und
   Stored Procedures.
5. DbExecption
   Wird zurückgegeben, wenn ein Fehler in der Datenquelle aufgetreten ist.
6. Error
   Enthält die Informationen aus einer Warnung oder einem Fehler, die von
   einer Datenquelle zurückgegeben werden.
7. ClientPermission
   Zugriff auf Sicherheitsattribute.
2. Data Provider: Command Builder
Der DataAdapter hat 4 Properties vom Typ Command:
• SelectCommand: Daten suchen
• InsertCommand: Daten einfügen
• UpdateCommand: Daten ändern
• DeleteCommand: Daten löschen

Ist das Select-Commando gesetzt, kann der DataAdapter das Select-Kommando
ausführen und mit den erhaltenen (Meta-)Daten die Insert-, Update- und Delete-
Kommandos automatisch erzeugen.
Folgendes muss beachtet werden:
• Das Resultat muss aus einer Tabelle bestehen (kein Join)
• Das Resultat muss einen Primärschlüssel enthalten
• Es wird ein zusätzlicher Round-trip zum SQL-Server erzeugt

 // Assumes that connection is a valid SqlConnection object and already opened
 SqlDataAdapter adapter = new SqlDataAdapter( "SELECT * FROM dbo.Customers", connection);
 adapter.Fill(dataSet, "Customers");
 SqlCommandBuilder builder = new SqlCommandBuilder(adapter);
 ...
 // generate statements to modify the DataSet
 builder.GetUpdateCommand();
2. Data Provider: Weitere Elemente
7 weitere Elemente des Data Provider:
1. Transaction
   Transaktionssteuerung der Befehle.
2. CommandBuilder
   Erzeugt automatisch Befehlseigenschaften eines DataAdapters.
3. ConnectionStringBuilder
   Erstellt und Verwaltet ConnectionStrings
4. Parameter
   Definiert Eingabe-, Ausgabe- und Rückgabewertparameter für Befehle und
   Stored Procedures.
5. DbExecption
   Wird zurückgegeben, wenn ein Fehler in der Datenquelle aufgetreten ist.
6. Error
   Enthält die Informationen aus einer Warnung oder einem Fehler, die von
   einer Datenquelle zurückgegeben werden.
7. ClientPermission
   Zugriff auf Sicherheitsattribute.
2. Data Provider: ConnectionStringBuilder
Bietet eine einfache und sichere Möglichkeit, den Inhalt von Connection Strings
zu erstellen und zu verwalten, die von der Klasse SqlConnection (SQL Server!)
verwendet werden.

    public SqlConnectionStringBuilder();
    public SqlConnectionStringBuilder(string connectionString);

    SqlConnectionStringBuilder builder =
        new SqlConnectionStringBuilder("server=(local);user id=ab;" +
             "password=Winter1234;initial catalog=AdventureWorks");

    // Now that the connection string has been parsed, you can work with individual items.
    builder.Password = "new@1Password";

    // You can refer to connection keys using strings, as well.
    builder["Server"] = ".";
    builder["Connect Timeout"] = 1000;
    builder["Trusted_Connection"] = true;

    Console.WriteLine(builder.ConnectionString);
2. Data Provider: Weitere Elemente
7 weitere Elemente des Data Provider:
1. Transaction
   Transaktionssteuerung der Befehle.
2. CommandBuilder
   Erzeugt automatisch Befehlseigenschaften eines DataAdapters.
3. ConnectionStringBuilder
   Erstellt und Verwaltet ConnectionStrings
4. Parameter
   Definiert Eingabe-, Ausgabe- und Rückgabewertparameter für Befehle und
   Stored Procedures.
5. DbExecption
   Wird zurückgegeben, wenn ein Fehler in der Datenquelle aufgetreten ist.
6. Error
   Enthält die Informationen aus einer Warnung oder einem Fehler, die von
   einer Datenquelle zurückgegeben werden.
7. ClientPermission
   Zugriff auf Sicherheitsattribute.
2. Data Provider: Parameter
• Command-Objekte verwenden Parameter, um Werte an SQL-Anweisungen oder
  Stored Prozedures zu übergeben, die eine Typprüfung und Validierung
  ermöglichen.
• Verbessern die Leistung, da sie dem DBMS helfen, den Befehl mit einem im
  Cache gespeicherten Execution Plan abzugleichen (Execution Plan Pooling auf
  dem SQL Server).
• Parameter müssen im ParameterDirection-Property: Input, InputOutput, Output
  oder ReturnValue angeben.
• Ein DbParameter-Objekt kann mit seinem Konstruktor oder durch Hinzufügen
  zur DbParameterCollection erstellt werden (Add-Methode).
• Die Syntax (Naming) für Parameter-Platzhalter ist abhängig von der
  Datenquelle (SQL Server: @, Oracle: :, OleDb & Odbd: ?)
• Die Datentypen müssen von C# und zurück konvertiert werden
2. Data Provider: Parameter
  public sealed class SqlParameter : System.Data.Common.DbParameter, ICloneable;

  static void GetSalesByCategory(string connectionString, string categoryName) {
      using (SqlConnection connection = new SqlConnection(connectionString)) {
           // Create the command to call a stored procedure and set its properties
           SqlCommand command = new SqlCommand();
           command.Connection = connection;
           command.CommandText = "SalesByCategory";
           command.CommandType = CommandType.StoredProcedure;

          // Add the input parameter, set its properties and add to the collection
          SqlParameter parameter = new SqlParameter();
          parameter.ParameterName = "@CategoryName";
          parameter.SqlDbType = SqlDbType.NVarChar;
          parameter.Direction = ParameterDirection.Input;
          parameter.Value = ;
          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."); }
          }
      }
  }
2. Data Provider: Parameter
Im Gegensatz zum Befehlstext werden Parameter als literaler Wert und nicht als
ausführbarer Code behandelt. Dies hilft, sich vor "SQL Injection"-Angriffen zu
schützen (SQL Server-Beispiel):

    SqlCommand command = new SqlCommand("SELECT * FROM Authentication " +
        "WHERE Username = @Username and Password = @Password", connection);
    command.CommandType = CommandType.Text;

    // Create the first parameter and add it to the collection
    SqlParameter userName = new SqlParameter();
    userName.ParameterName = "@Username";
    userName.Value = txt1.Text;
    command.Parameters.Add(userName);

    // Create the second parameter and add it to the collection
    SqlParameter password = new SqlParameter();
    password.ParameterName = "@Password";
    password.Value = txt2.Text;
    command.Parameters.Add(password);

    SqlDataReader reader = command.ExecuteReader();
    if (reader.HasRows) {
         Console.WriteLine("{0}", reader[0]);
    }
    else { errorlbl.Text = "Incorrect username and password"; }
2. Data Provider: Weitere Elemente
7 weitere Elemente des Data Provider:
1. Transaction
   Transaktionssteuerung der Befehle.
2. CommandBuilder
   Erzeugt automatisch Befehlseigenschaften eines DataAdapters.
3. ConnectionStringBuilder
   Erstellt und Verwaltet ConnectionStrings
4. Parameter
   Definiert Eingabe-, Ausgabe- und Rückgabewertparameter für Befehle und
   Stored Procedures.
5. DbExecption
   Wird zurückgegeben, wenn ein Fehler in der Datenquelle aufgetreten ist.
6. Error      Error-Objekt ist Property of
   Enthält die Informationen aus einer Warnung oder einem Fehler, die von
   einer Datenquelle zurückgegeben werden.
7. ClientPermission
   Zugriff auf Sicherheitsattribute.
2. Data Provider: DbExecption
Die Klasse DbException ist die Basisklasse für alle Ausnahmen. Jeder Data
Provider hat eine eigene Exception Klasse:
1.   SqlException Klasse
2.   OracleException Klasse
3.   OdbcException Klasse
4.   OleDbException Klasse

     try {
         // Do work here.
     }
     catch (SqlException ex) {
         for (int i = 0; i < ex.Errors.Count; i++) {
              errorMessages.Append("Index #" + i + "\n" +
                  "Message: " + ex.Errors[i].Message + "\n" +
                  "Line Number: " + ex.Errors[i].LineNumber + "\n" +
                  "Source: " + ex.Errors[i].Source + "\n" +
                  "Procedure: " + ex.Errors[i].Procedure + "\n");
         }
         Console.WriteLine(errorMessages.ToString());
     }
     finally {
         // Perform cleanup here.
     }
2. Data Provider: Weitere Elemente
7 weitere Elemente des Data Provider:
1. Transaction
   Transaktionssteuerung der Befehle.
2. CommandBuilder
   Erzeugt automatisch Befehlseigenschaften eines DataAdapters.
3. ConnectionStringBuilder
   Erstellt und Verwaltet ConnectionStrings
4. Parameter
   Definiert Eingabe-, Ausgabe- und Rückgabewertparameter für Befehle und
   Stored Procedures.
5. Exception
   Wird zurückgegeben, wenn ein Fehler in der Datenquelle aufgetreten ist.
6. Error
   Enthält die Informationen aus einer Warnung oder einem Fehler, die von
   einer Datenquelle zurückgegeben werden.
7. ClientPermission
   Zugriff auf Sicherheitsattribute.
2. Data Provider: ClientPermission
Die Klasse DbDataPermission stellt sicher, dass ein Benutzer über eine
Sicherheitsstufe verfügt, die für den Zugriff auf Daten angemessen ist:
1.   SqlClientPermission Klasse
2.   OracleClientPermission Klasse
3.   OdbcClientPermission Klasse
4.   OleDbClientPermission Klasse
Nächste Woche:
1.   DataReader
2.   DataSet
3.   LINQ to SQL
4.   Entity Framework
Fragen?

          Uff!
Sie können auch lesen