EDM für bestehende Datenbank mit Code First

Lies in den Artikel rein und unten bekommst Du ein unschlagbares Angebot!

Wenn Sie ein Entity Data Model mit der Vorlage “Code First aus Datenbank” auf Basis einer bestehenden Datenbank erstellen, haben Sie vielleicht Pech und die Namen der Tabellen der Datenbank und der enthaltenen Felder lauten nicht so, wie Sie die Entitätsklassen, die DbSet-Elemente und die Eigenschaften der Klassen nennen möchten. Dann haben Sie verschiedene Möglichkeiten: Zum Beispiel können Sie die Bezeichnungen in der Datenbank anpassen. Das geht aber oft nicht, weil vielleicht noch andere Frontends auf die gleiche Datenbank zugreifen. Dann haben Sie noch die Möglichkeit, die Bezeichnungen von Datenbank und Entity Data Model so zu mappen, dass beide Seiten zufrieden sind. Wie letzteres gelingt, zeigen wir im vorliegenden Artikel am Beispiel der Südsturm-Datenbank.

Einfaches Beispiel: tblFotos

Wir starten mit einem sehr einfachen Beispiel, nämlich der Tabelle tblFotos. Diese haben wir als Tabelle zum Speichern von Fotos erstellt, die mit einer PowerApp über das Smartphone aufnehmen wollen. Dabei haben wir die Tabelle leichtsinnigerweise tblFotos genannt statt einfach Fotos ohne Präfix. Wenn wir nun ein Entity Data Model erstellen, erhalten wir für die Klasse FotoverwaltungContext.db etwa den folgenden Code:

Imports System.ComponentModel.DataAnnotations.Schema
Partial Public Class FotoverwaltungContext
     Inherits DbContext
     Public Sub New()
         MyBase.New("name=FotoverwaltungContext")
     End Sub
     Public Overridable Property tblFotos As DbSet(Of tblFotos)
     Protected Overrides Sub OnModelCreating(ByVal modelBuilder As DbModelBuilder)
     End Sub
End Class

Hier hätten wir gern den Namen der Property für das DbSet so geändert, dass es Fotos statt tblFotos heißt und Elemente des Typs Foto enthält (die auch noch tblFotos heißen). In der Entitätsklasse tblFotos geht es so weiter. Diese hat nach dem Erstellen des Entity Data Models den folgenden Code erhalten:

Imports System.ComponentModel.DataAnnotations
Imports System.ComponentModel.DataAnnotations.Schema
Partial Public Class tblFotos
     Public Property ID As Integer
     <Column(TypeName:="image")>
     <Required>
     Public Property Foto As Byte()
End Class

Wir wollen dies Schritt für Schritt so anpassen, dass wir mit einer Konstruktor-Methode für das Fenster MainWindow wie der folgenden auf die Daten zugreifen können:

Class MainWindow
     Public Sub New()
         Dim dbContext As FotoverwaltungContext
         dbContext = New FotoverwaltungContext
         Dim foto As Foto
         foto = dbContext.Fotos.First()
         MessageBox.Show(foto.ID.ToString())
     End Sub
End Class

Wir wollen also ein DbSet namens Fotos verwenden und damit auf Elemente des Typs Foto zugreifen. Dazu müssen wir dem Entity Data Model auf irgendeine Weise mitteilen, dass es das DbSet namens Fotos auf die Tabelle tblFotos mappen soll und die Klasse Foto auf die einzelnen Datensätze.

Mapping in der Methode OnModelCreating

Der richtige Ort für ein solches Mapping ist die Methode OnModelCreating, die beim Erstellen des Entity Data Models auf Basis der Vorlage Code First aus Datenbank automatisch in der Klasse FotoverwaltungContext angelegt wurde. Der erste Schritt ist das Umbenennen der Klasse tblFotos in Foto. Das erledigen wir ganz einfach, indem wir den entsprechenden Eintrag im Projektmappen-Explorer markieren, diesen nochmals anklicken und dann die Bezeichnung ändern. Danach erscheint noch eine Meldung, die fragt, ob Verweise auf das Codeelement angepasst werden sollen (siehe Bild 1).

Ändern eines Klassennamens

Bild 1: Ändern eines Klassennamens

Wenn Sie hier auf Ja klicken, werden in unserer kleinen Beispielanwendung folgende Änderungen durchgeführt:

  • Die Bezeichnung der Klasse wird ebenfalls in Foto geändert.
  • In der Klasse FotoverwaltungContext wird der Typ der Klasse des DbSets ebenfalls geändert:
Partial Public Class FotoverwaltungContext
     Inherits DbContext
     ...
     Public Overridable Property tblFotos As DbSet(Of Foto)
     ...
End Class

In dieser Klasse sind dann weitere Änderungen nötig. Anschließend sieht die oben bereits teilweise geänderte Zeile mit der Definition des DbSet wie folgt aus:

Public Overridable Property Fotos As DbSet(Of Foto)

Mapping hinzufügen

Damit passen die Deklarationen der Klasse und des DbSet-Elements nun zu dem Code, den wir für die Konstruktor-Methode unseres Fensters MainWindow.xaml erstellt haben. Was geschieht nun, wenn wir die Anwendung starten

Wir erhalten einen unerwarteten Fehler: Visual Studio bemängelt, dass wir eine Eigenschaft namens Foto in der gleichnamigen Klasse verwenden (siehe Bild 2). Damit erhalten wir also noch ein Problem, das aus der Benennung der Tabellen und Felder der Beispieldatenbank resultiert. Das Feld Foto können wir nicht mit dem Eigenschaftsnamen Foto ansprechen, da eine Klasse keine Eigenschaften besitzen darf, die genauso heißen wir die Klasse selbst. Also ändern wir den Namen der Eigenschaft in der Klasse Foto auf Fotodaten:

Fehler beim Zugriff auf die Klasse

Bild 2: Fehler beim Zugriff auf die Klasse

Partial Public Class Foto
     ...
     Public Property Fotodaten As Byte()
End Class

Nach einem erneuten Start der Anwendung erhalten wir dann die Fehler, mit denen wir gerechnet hätten. Der erste lautet wie folgt und er tritt beim Zugriff auf die Daten über dbContext.Fotos.First auf (siehe auch Bild 3):

Fehler beim Zugriff auf die Tabelle

Bild 3: Fehler beim Zugriff auf die Tabelle

System.InvalidOperationException: "Die Sequenz enthält keine Elemente."

Das ist etwas überraschend, denn wir hatten mit einem Fehler gerechnet, der durch eine fehlende Tabelle ausgelöst wird. Schauen wir uns die Eigenschaften der Auflistung Fotos wie in Bild 4 an, sehen wir, dass es Entity Framework anscheinend versucht, auf eine Tabelle namens Fotoes zuzugreifen. Das ist offensichtlich die Plural-Form der Klasse Foto, die Entity Framework automatisch gebildet hat, um auf die Tabelle zuzugreifen.

Der Zugriff erfolgt auf die nicht vorhandene Tabelle Fotoes

 

Schreibe einen Kommentar