NET

Werbung
1
4. .NET
• Kombination von Frameworks, Sprachen, Werkzeugen, Webservices, . . .
zur einfachen Entwicklung von Windows-Applikationen (inkl. Web-Appl.)
• gemeinsames Laufzeitsystem CLR (Common Language Runtime):
abstrakte/virtuelle Maschine für alle .NET-Srachen
(VB, C#, J#, Managed C++, Java, Fortran, Java, Haskell, Perl, . . . )
• basiert auf gemeinsamer Zwischensprache CIL (Common Intermediate Language)
• gemeinsames Typsystem CTS (Common Type System)
• (sofortige) Just-in-time-Compilierung (→ Sicherheit)
• umfassende OO-Klassenbibliothek (Kollektionen, Threads, Reflection, XMLVerarbeitung, Windows Forms, Web Forms, ADO.NET, ASP.NET)
• Versionierung (“Rettung aus der DLL-Hölle”)
• sehr gute Unterstützung von Webservices
2
4.1 C#
• sehr Java-ähnliche OO-Programmiersprache mit
? (Einfach-)Vererbung, Interfaces
? generische Typen (besser als in Java, da in CLR)
? Garbage-Collection
? Code-Verifikation (z.B. int nicht als Referenz)
? Exceptions (müssen nicht abgefangen oder deklariert werden)
? Reflection
? Iteratoren, foreach-Schleife
? Assembly: (vgl. .jar-Datei in Java)
∗ Sammlung von Klassen mit Manifest (Inhaltsverzeichnis) und
Metadaten über Schnittstellen
∗ als EXE oder DLL bereitgestellt (in Ordner oder Global Assembly Cache)
∗ kein Eintrag in Windows Registry erforderlich
3
Unterschiede zu Java
• auch Basistypen als Objekte verwendbar (Auto-Boxing und -Unboxing)
• (neben Referenztypen) Werttypen (structs, enum); auf Stack statt Heap
• neben call-by-value auch call-by-reference (T m(ref T2 p){...}, o.m(ref a))
• mehrdimenionale Arrays als Speicherblock (statt Arrays von Arrays)
z.B. int[,] a = new int[4,5]; ... x = a[2,0];
• Property =
ˆ Attribut mit getter und setter, z.B.:
class C{
private in anzahl;
public int Anzahl{set{anzahl = value;}
get{return anzahl}}
}
C o; ... o.Anzahl = o.Anzahl + 1;
4
Unterschiede zu Java (2)
• Namensraum (=
ˆ package) auf mehrere Verzeichnisse aufteilbar
• eine Datei umfasst ggf. mehrere Namensräume mit ggf. mehreren Klassen
• in unsafe-Programmteilen können Typregeln ignoriert werden
• keine anonymen Klassen (dafür (ggf. anonyme) Methoden (delegates))
zur Ereignisbehandlung
• Objekte ggf. auf dem Stack (statt Heap)
• (eingeschränktes) goto
• überschreibbare Methoden als virtual deklariert
(überschreibende als override, verdeckende als new)
• sealed-Klassen haben keine Unterklassen (vgl. final in Java)
5
4.2 ASP.NET
• zur Gestaltung dynamischer Webseiten mit Interaktion über Formulare
• Webform: HTML-Seite mit integrierten Steuerelementen
• wird transformiert in reines HTML mit versteckten Formularfeldern und
serverseitigem Code zur Ereignisbehandlung
• nicht nur das Abschicken eines Formulars, sondern die Bedienung jedes Steuerelements können ein Ereignis auslösen, das serverseitig bearbeitet wird
• das Ausfüllen eines Formulars und seine Bearbeitung erfolgen in mehreren httpRoundtrips zwischen Server und Browser
6
ASP.NET (Fortsetzung)
• Code behind: im Webformular kann auf Code zurückgegriffen werden, der in
einer Oberklasse der Klasse zum Webform bereitgestellt wurde
• dadurch saubere Trennung von HTML (Webform) und C#-Code
• Unterschied zu JSP: ein Webform beschreibt die in Roundtrips befindliche
aktuelle Seite (nicht die nächste)
• zum Wechsel der Seite muss ein Link oder eine Umleitung genutzt werden
• Masterseiten erlauben ein einheitliches Layout eines Webauftritts
• Sitzungsattribut speichert Informationen Sitzungs-übergreifend (wie JSP)
• Cookies können gesetzt und ausgelesen werden
• Validatoren für Benutzereingaben (werden in JavaScript übersetzt)
7
Beispiel: Webform
<%@ Page Language="C#" AutoEventWireup="true"
CodeBehind="BiblLogin.aspx.cs" Inherits="Bibliothek.BiblLogin" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Willkommen in der Bibliothek</title>
</head>
<body>
<h1>Willkommen in der Bibliothek</h1>
<form id="form1" runat="server">
<div>
<asp:Label ID="PasswortLabel" runat="server" Text="Passwort"></asp:Label>
<asp:TextBox ID="Passwort" TextMode="Password" runat="server"></asp:TextBox></br>
<asp:RequiredFieldValidator ID="val" ControlToValidate="Passwort"
ErrorMessage="Passwort angeben!" runat="server"/>
<asp:Button ID="Ok" runat="server" Text="Ok" OnClick="Login"/>
</div>
</form>
</body>
</html>
8
Beispiel: An Browser übertragene HTML-Seite
(ohne Validator)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head><title>Willkommen in der Bibliothek</title></head>
<body>
<h1>Willkommen in der Bibliothek</h1>
<form name="form1" method="post" action="BiblLogin.aspx" id="form1">
<div>
<input type="hidden" name=" VIEWSTATE" id=" VIEWSTATE"
value="/wEPDwUKMTIxNDIyOTM0MmRkBODT+ziyM71eMrjNc9ap6hwWoCg=" />
</div>
<div>
<span id="PasswortLabel">Passwort</span>
<input name="Passwort" type="text" id="Passwort" /></br>
<input type="submit" name="Ok" value="Ok" id="Ok" />
</div>
<div>
<input type="hidden" name=" EVENTVALIDATION" id=" EVENTVALIDATION"
value="/wEWAwKclIP9BgLSxaDECgLh777vDG/iFwXGlUrZVFnVqg/27x7y75wb" />
</div>
</form>
</body>
</html>
9
Beispiel: Zugehöriger Hintergrundcode
using
using
...
using
using
System;
System.Data;
System.Web.UI.HtmlControls;
Bibliothek.Web;
namespace Bibliothek{
public partial class BiblLogin : System.Web.UI.Page {
public void Login(object sender, EventArgs ev){
string passw = Passwort.Text;
if (passw != "geheim123"){
Context.Session.Add("Login",false);
Passwort.Text = "Fehlerhafte Eingabe";}
else {Context.Session.Add("Login",true);
Response.Redirect("Web/Bibliothek.aspx");}}
}
}
• hinzu kommt eine automatisch generierte partielle Klasse BiblLogin
• hierin werden Variablen zum Zugriff auf Formularwerte wie Passwort deklariert
10
Beispiel 2: Webform “Benutzer Anlegen”
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="BenutzerAnlegenWeb.aspx.cs"
Inherits="Bibliothek.Web.BenutzerAnlegenWeb" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ...>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server"><title>Benutzer Anlegen</title></head>
<body>
<h1>Benutzer Anlegen</h1>
<form id="form1" runat="server">
<div>
<asp:Label ID="NameLabel" runat="server" Text="Name"></asp:Label>
<asp:TextBox ID="Bname" runat="server"></asp:TextBox><br/>
<asp:Label ID="Adresslabel" runat="server" Text="Adresse"></asp:Label>
<asp:TextBox ID="Badresse" runat="server"></asp:TextBox><br/>
<asp:Button ID="Ok" runat="server" Text="Ok" OnClick="Anlegen"/>
</div>
</form>
<a href="BenutzerverwaltungWeb.aspx">zurück</a>
</body>
</html>
11
Beispiel: Hintergrundcode zu “Benutzer Anlegen”
using Bibliothek.Geschäftslogik; ...
namespace Bibliothek.Web {
public partial class BenutzerAnlegenWeb : System.Web.UI.Page {
protected void Page Load(object sender, EventArgs e) {
if ((Context.Session["Login"] == null) ||
(Convert.ToBoolean(Context.Session["Login"]) == false))
Response.Redirect("BiblLogin.aspx");}
public void Anlegen(object sender, EventArgs ev) {
string name = Bname.Text;
string adresse = Badresse.Text;
if ((name == null) || (name == ""))
Response.Redirect("Fehler.htm");
try{ Benutzerverwaltung bv = new Benutzerverwaltung();
bv.BenutzerAnlegen(name,adresse);
Response.Write("Benutzer "+name+" gespeichert!");
Bname.Text = ""; Badresse.Text = "";}
catch(Exception){Response.Redirect("Fehler.htm");}}
}
}
12
4.3 ADO.NET
• Framework zum Zugriff auf Datenbanken und andere Datenquellen
• verbindsorientierter oder verbindungsloser Zugriff
• Schritte beim verbindungsorientierten Zugriff:
? Verbindung zur DB aufbauen
? wiederhole:
∗ SQL-Anweisung mit Platzhaltern (@platzhaltername) erstellen
∗ Platzhalter mit Werten befüllen,
z.B. mit AddWithValue("@platzhaltername",wert)
∗ SQL-Anweisung ausführen
(ExecuteScalar, ExecuteNonQuery, ExecuteReader)
∗ Ergebnisse verarbeiten (ggf. in Schleife)
? Verbindung abbauen
13
Beispiel: Geschäftslogik mit ADO.NET
using System.Data.SqlClient; ...
namespace Bibliothek.Geschäftslogik{
public class Benutzerverwaltung{
public void BenutzerAnlegen(string name, string adresse){
SqlConnection verbindung =
new SqlConnection(ConfigurationManager.ConnectionStrings["Bibliothek"].ConnectionString);
verbindung.Open();
string sqltext = "SELECT COUNT(*) FROM Benutzer WHERE Name = @name";
SqlCommand sql = new SqlCommand(sqltext, verbindung);
sql.Parameters.AddWithValue("@name", name);
int anzahl = (int) sql.ExecuteScalar();
if (anzahl > 0) throw new Exception("Name schon vergeben");
else{ sqltext = "INSERT INTO Benutzer (Name, Adresse)"
+ "VALUES (@name, @adresse);"
+ "SELECT CAST(SCOPE IDENTITY() AS INT);";
sql = new SqlCommand(sqltext, verbindung);
sql.Parameters.AddWithValue("@name", name);
sql.Parameters.AddWithValue("@adresse", adresse);
int bid = (int) sql.ExecuteScalar();}
verbindung.Close();}}
}
14
Beispiel 2: Mengenwertige Anfragen verarbeiten (1)
public string AusleiheAnzeigen(int kundennr) {
SqlConnection verbindung =
new SqlConnection(ConfigurationManager.ConnectionStrings["Bibliothek"].ConnectionString);
try { verbindung.Open(); }
catch (Exception e) { Console.Write(e); }
string sqltext =
"SELECT Name, Bid, Bezeichnung, Inventarnr, Datum "
+ "FROM Benutzer B, Ausleihe A, Exemplar E, Medium M "
+ "WHERE B.Bid = @bid AND B.Bid = A.Benutzer AND A.Exemplar = E.Inventarnr "
+ "
AND E.Medium = M.Id AND M.Medientyp = 0; "
+ "SELECT Name, Bid, Bezeichnung, Inventarnr, Datum "
+ "FROM Benutzer B, Ausleihe A, Exemplar E, Medium M "
+ "WHERE B.Bid = @bid AND B.Bid = A.Benutzer AND A.Exemplar = E.Inventarnr "
+ "
AND E.Medium = M.Id AND Medientyp = 1";
SqlCommand sql = new SqlCommand(sqltext, verbindung);
sql.Parameters.AddWithValue("@bid", kundennr);
SqlDataReader erg = sql.ExecuteReader();
... (b.w.) ...
15
Beispiel 2: Mengenwertige Anfragen verarbeiten (2)
... (s.o.) ...
string[] medientext = { "Bücher", "CDs" };
string ausgabe = ""; int i = 0;
do {
ausgabe += "<h1>Ausgeliehene " + medientext[i] + "</h1>";
ausgabe += "<Table border="1">";
ausgabe += "<tr><th>Name</th><th>Benutzernr</th><th>Bezeichnung</th>";
ausgabe += "<th>Inventarnr</th><th>Datum</th></tr>";
while (erg.Read()) {
object[] werte = new object[erg.FieldCount];
erg.GetSqlValues(werte);
ausgabe += "<tr>";
foreach (object wert in werte)
ausgabe += "<td>"+wert.ToString()+"</td>";
ausgabe += "</tr>";}
ausgabe += "</Table>";
i++;}
while (erg.NextResult());
verbindung.Close();
return ausgabe;
}
16
Anmerkungen zu den Beispielen
• statt SQL direkt aus der Geschäftslogik aufzurufen,
kann man eine OR-Mapping-Schicht zwischenschalten
• Beispiel 2 vermischt der Kürze halber Präsentationslogik und Geschäftslogik
• deutlich besser wäre:
? eine Datenstruktur mit Ergebnissen (DTO) an Präsentationsschicht liefern
? (nur) die Präsentationschicht HTML-Code generieren lassen
• die Transaktionsverarbeitung fehlt noch (s.u.)
17
Transaktionsverarbeitung
• Schritte: BeginTransaction, jedes SqlCommand der Tr. zuordnen,
Commit bzw. Rollback
• lokale oder verteilte Transaktionen mit vorgegebenem Isolationslevel
• Isolationslevel:
? ReadUncommitted: kein Schutz, Sperren werden ignoriert
? ReadCommitted:
∗ Tupel können nur nach commit gelesen werden
∗ die zugehörigen Tabellen können sich während der Transaktion ändern
∗ wiederholtes Lesen einer Tabelle liefert ggf. andere Ergebnisse
? ReadRepeatable: wiederholte Abfrage liefern die gleichen Ergebnisse
? Serializable
? Trade-off zwischen Effizienz und unerwünschten Effekten
18
Beispiel: Transaktionsverarbeitung mit ADO.NET
public void BenutzerAnlegen(string name, string adresse){
SqlConnection verbindung =
new SqlConnection(ConfigurationManager.ConnectionStrings["Bibliothek"].ConnectionString);
SqlTransaction trans = null;
try {
verbindung.Open();
trans = verbindung.BeginTransaction(IsolationLevel.ReadCommitted);
string sqltext = "SELECT COUNT(*) FROM Benutzer WHERE Name = @name";
SqlCommand sql = new SqlCommand(sqltext, verbindung);
sql.Parameters.AddWithValue("@name", name);
sql.Transaction = trans;
int anzahl = (int) sql.ExecuteScalar();
if (anzahl > 0) throw new Exception("Name schon vergeben");
else{ sqltext = "INSERT INTO Benutzer (Name, Adresse)"
+ "VALUES (@name, @adresse);"
+ "SELECT CAST(SCOPE IDENTITY() AS INT);";
sql = new SqlCommand(sqltext, verbindung);
sql.Parameters.AddWithValue("@name", name);
sql.Parameters.AddWithValue("@adresse", adresse);
sql.Transaction = trans;
int bid = (int) sql.ExecuteScalar();
trans.Commit();}}
catch (Exception e) {if (trans != null) trans.Rollback();
Console.WriteLine(e);}
finally {verbindung.Close();}
}
Herunterladen