Mit einem Exception-Filter kann man zusätzlich zu den Exception-Klassen in den catch-Blöcken noch weiter zwischen verschiedenen Fällen differenzieren. Unterstützung für Exception-Filter gibt es seit .NET 1.0 in der Common Language Runtime (CLR). Aber zunächst haben nur Visual Basic .NET und F# diese Möglichkeit in der Sprachsyntax auch angeboten. Erst mit C# 6.0 ist dieses syntaktische Zuckerstück auch in die C#-Sprachsyntax eingezogen. Man verwendet dazu das Schlüsselwort when (Listing 1).
try { var datei = System.IO.File.ReadLines(filename); } catch (ArgumentException) when (filename == "") { Console.WriteLine("Ohne Dateiname macht diese Aktion keinen Sinn!"); } catch (ArgumentException ex) when (ex.Message.Contains("Illegales")) { Console.WriteLine("Ungültige Zeichen im Dateinamen: " + filename); } catch (ArgumentException ex) { Console.WriteLine("Ungültige Angabe: " + filename + ":" + ex.Message); } catch (NotSupportedException ex) when (ex.Message.Contains("format")) { Console.WriteLine("Ungültiges Format!"); } catch (NotSupportedException ex) { Console.WriteLine("Nicht unterstützt: " + ex.Message); } catch (FileNotFoundException ex) { Console.WriteLine("Datei " + filename + " nicht gefunden"); } catch (Exception ex) { Console.WriteLine("Anderer Fehler: " + ex.Message); }
Mit Exception-Filtern kann das „Rethrowing“ von Laufzeitfehlern vermieden werden, weil die zu behandelnden Fehler besser eingrenzt werden können. Das ist besonders sinnvoll bei dem sehr allgemeinem Fehlertyp COMException, wo die eigentliche Ursache per Eigenschaft ErrorCode ausgelesen werden muss.
try { RessourcenZugriff(); } catch (System.Runtime.InteropServices.COMException ex) { if ((uint)ex.ErrorCode != 0x80070005) throw ex; Console.WriteLine("Zugang verboten!"); }
try { RessourcenZugriff(); } catch (System.Runtime.InteropServices.COMException ex) when ((uint)ex.ErrorCode == 0x80070005) { Console.WriteLine("Zugang verboten!"); }
Exception-Filter sind mit Bedacht einzusetzen: Um die Übersichtlichkeit des Programmcodes zu bewahren und Seiteneffekte zu vermeiden, sollte man in Exception-Filtern keine weiteren Methoden aufrufen, die weitere Aktionen auslösen. Mike Magruder aus dem CLR-Team empfiehlt: „To keep your world safe and simple try to limit yourself to expressions that only access the exception object, and don’t modify anything.“
Setzen des Concurrency Mode für alle Spalten in der EDMX-Datei
In der Grundeinstellung verfolgt Microsofts Entity Framework bei schreibenden Datenzugriffen die Strategie „Der Letzte gewinnt“. Das ist jedoch in der Praxis oft kein gangbarer und für die Nutzer auch kein akzeptabler Weg. Man kann aber bei Entity Framework das optimistische Sperren (wie beim ADO.NET Dataset) aktivieren.
Beim Code-based Modeling erfolgt das durch Annotation mit dem ConcurrencyCheckAttribute, egal, ob die Entitätsklasse selbst geschrieben oder aus einer bestehenden Datenbank von Visual Studio per Reverse Engineering generiert wurde. Lästiger ist es beim Einsatz des Entity Data Model Designers für Database First oder Model First: Hier muss der Softwareentwickler jede Property im Designer anklicken und dort die Eigenschaft Concurrency Mode auf den Wert Fixed festlegen. Leider hat Microsoft in den Entity Framework Designer keine Möglichkeit eingebaut, den Standardwert für die Eigenschaft für Concurrency Mode auf den Wert Fixed zu bestimmen.
Wenn man den Concurrency Mode nicht manuell für jede Property setzen möchte (was nicht nur lästig ist, sondern auch fehleranfällig, weil man leicht eine Property übersehen kann), dann muss man sich ein Werkzeug schreiben, dass die EDMX-Datei ändert. Das ist keine Hexerei, sondern recht einfach, da die EDMX-Datei im XML-Format vorliegt. Die Lösung zeigt Listing 2. Aufrufen kann man diesen Code dann mit
ConcurrencyModeUtil.ChangeConcurrencyMode(@"x:\... \Modell.edmx", ConcurrencyMode.Fixed)
in einer Kommandozeilenanwendung, die man als in Visual Studio als Pre-Build-Event in die Projekteigenschaften einträgt. Und schon ist immer sichergestellt, dass alle Properties den Concurrency Mode korrekt gesetzt haben (Listing 2).
/// <summary> /// Zur Ausführung zur Entwicklungszeit /// Ändert alle Properties im Conceptual Model einer EDMX-Datei auf ConcurrencyMode = fixed oder = none /// </summary> /// <param name="edmxPath">Pfad zur EDMX-Datei.</param> /// <param name="value">ConcurrencyMode none oder fixed.</param> public static void ChangeConcurrencyMode(string edmxPath, ConcurrencyMode mode) { // öffne EDMX-Datei als XML-Dokument XDocument xmlDoc = XDocument.Load(edmxPath); // Suche Element <ConceptualModels> var conceptualModel = xmlDoc.Descendants().SingleOrDefault (p => p.Name.LocalName == "ConceptualModels"); // Suche alle Unterelemente <Property>, wo der ConcurrencyMode nicht dem gewünschten Wert entspricht IEnumerable<XElement> properties = from el in conceptualModel.Descendants() where el.Name.LocalName == "Property" && (string)el.Attribute("ConcurrencyMode") != mode.ToString() select el; bool modified = false; // Setze ConcurrencyMode in den gefundenen Properties foreach (XElement el in properties) { modified = true; el.SetAttributeValue("ConcurrencyMode", mode.ToString()); Console.WriteLine(el.Attribute("Name") + ": " + el.Attribute("ConcurrencyMode")); } // Speichern, falls es Änderungen gab if (modified) { xmlDoc.Save(edmxPath); Console.WriteLine("Datei " + edmxPath + " wurde geändert!"); } }
Buchempfehlung
In den vergangenen Jahren haben Dr. Holger Schwichtenberg und Manfred Steyer im „Windows Developer“ regelmäßig Tipps und Tricks aus ihrem Alltag als Softwareentwickler, Berater und Trainer für .NET- und webbasierte Anwendungen veröffentlicht. Das vorliegende Buch ist eine aktualisierte und deutlich erweiterte Zusammenfassung dieser Tipps und Tricks. Es umfasst sowohl das .NET Framework und seine zahlreichen Teilbibliotheken als auch die beliebte JavaScript-Bibliothek AngularJS sowie die Entwicklungsumgebung Visual Studio und ergänzende Werkzeuge.
Mehr Infos: www.entwickler-press.de/Dotnet-Praxis
Windows Developer
Dieser Artikel ist im Windows Developer erschienen. Windows Developer informiert umfassend und herstellerneutral über neue Trends und Möglichkeiten der Software- und Systementwicklung rund um Microsoft-Technologien.
Natürlich können Sie den Windows Developer über den entwickler.kiosk auch digital im Browser oder auf Ihren Android- und iOS-Devices lesen. Außerdem ist der Windows Developer weiterhin als Print-Magazin im Abonnement erhältlich.