Tipps und Tricks rund um .NET und Visual Studio

Exception-Filter in C# 6.0
Kommentare

Dr. Holger Schwichtenberg (MVP) alias „der Dotnet-Doktor“, ist technischer Leiter des auf .NET und Webtechniken spezialisierten Beratungs- und Schulungsunternehmens www.IT-Visions.de. Er gehört durch zahlreiche Fachbücher zu den bekanntesten Experten für .NET und Visual Studio in Deutschland. Dr. Holger Schwichtenberg unterrichtet in Lehraufträgen an den Fachhochschulen Münster und Graz. Seit 1999 ist er Sprecher auf jeder BASTA!.

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!");
  }
}

Buchempfehlungdotnet_praxis

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

Windows DeveloperDieser 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. In unserem Shop ist der Windows Developer ferner im Abonnement oder als Einzelheft erhältlich.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -