NET 2: ADO.NET Thema Lektion 8 und 9
←
→
Transkription von Seiteninhalten
Wenn Ihr Browser die Seite nicht korrekt rendert, bitte, lesen Sie den Inhalt der Seite unten
.NET 2: ADO.NET .NET Framework .NET Core?! Es wird versucht, jeweils darauf hinzuweisen, falls Unterschiede bekannt sind…
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
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/
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)
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)
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).
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