{"id":55000253,"date":"2021-02-01T00:00:00","date_gmt":"2021-04-29T18:36:57","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=253"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Code_First_Mapping_per_DataAnnotation","status":"publish","type":"post","link":"https:\/\/vbentwickler.de\/Code_First_Mapping_per_DataAnnotation\/","title":{"rendered":"Code First Mapping per DataAnnotation"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/vg02.met.vgwort.de\/na\/018ee8b0090f41bdab253af14455a3cd\" width=\"1\" height=\"1\" alt=\"\"><\/p>\n<p><b>Wenn Sie ein Code First-Entity Data Model entwerfen, gibt es bestimmte Konventionen, die standardm&auml;&szlig;ig greifen. So hei&szlig;en Entit&auml;ten wie der Singular der zugrunde liegenden Tabellennamen oder der Prim&auml;r- und Fremdschl&uuml;ssel werden aus Feldern abgeleitet, welche die Zeichenkette ID enthalten &#8211; gegebenenfalls kombiniert mit dem Entit&auml;tsnamen. Wenn Sie mit einem Datenmodell daherkommen, dessen Tabellen das Pr&auml;fix &#8220;tbl&#8221; mitbringen, wollen Sie dieses nicht in den Entit&auml;tsnamen wiederfinden und gegebenenfalls m&ouml;chten (oder m&uuml;ssen) Sie auch noch Feldnamen &auml;ndern und diese anschlie&szlig;end mappen. Eine M&ouml;glichkeit dazu bieten die DataAnnotations, die wir in diesem Artikel beschreiben.<\/b><\/p>\n<p>Im Artikel <b>Code First Mapping per Fluent API <\/b>(<b>www.datenbankentwickler.net\/252)<\/b> haben wir gezeigt, wie Sie die Entit&auml;tsklassen eines Entity Data Models auf die Tabellen eines Datenmodells einer SQL Server-Datenbank mappen k&ouml;nnen beziehungsweise wie Sie daf&uuml;r sorgen k&ouml;nnen, dass die Tabellen, Felder und Beziehungen der Tabellen beim Erstellen einer neuen Datenbank auf Basis von Code First nach Ihren W&uuml;nschen erstellt werden k&ouml;nnen. Dabei haben wir ausschlie&szlig;lich die Methoden der Fluent API verwendet, die in einer speziellen Methode namens <b>OnModelCreating <\/b>angelegt werden. Im vorliegenden Artikel wollen wir eine Alternative dazu vorstellen, n&auml;mlich die <b>DataAnnotations<\/b>. Dabei handelt es sich um &#8220;Anmerkungen&#8221;, die direkt in die jeweiligen Entit&auml;tsklassen eingetragen werden. Im Gegensatz zu den Methoden, die wir mit der Fluent API in der Methode <b>OnModelCreating <\/b>hinterlegen, landen die DataAnnotations unmittelbar bei den betroffenen Klassen und Eigenschaften. Wir wollen versuchen, die Mapping-Eigenschaften, die wir im oben genannten Artikel mit der Fluent API vorgenommen haben, mit den DataAnnotations zu reproduzieren. Wir verwenden also die gleichen Entit&auml;tsklassen und wollen das gleiche Datenmodell daraus erstellen beziehungsweise mappen wie in diesem Artikel.<\/p>\n<h2>Erstellen versus Mapping<\/h2>\n<p>In den Beispielen dieses Artikels, in denen wir die Anpassungen von Entity Data Model zu den Tabellen des zu erzeugenden Datenmodells Schritt f&uuml;r Schritt anpassen, erstellen wir die Datenbank einmal neu und f&uuml;hren die nachfolgend beschriebenen &Auml;nderungen Schritt f&uuml;r Schritt aus. Das erledigen wir mit drei Methoden, die wir &uuml;ber die Paket-Manager-Konsole absetzen. Diese Methoden lauten:<\/p>\n<ul>\n<li><b>Enable-Migration<\/b>: Aktiviert die Migrationen f&uuml;r das Entity Data Model. Dieser Schritt ist nur einmal vor dem ersten Aufruf der nachfolgend beschriebenen Anweisung <b>Add-Migration <\/b>notwendig.<\/li>\n<li><b>Add-Migration <Bezeichnung><\/b>: F&uuml;gt eine neue Migration hinzu. Beim ersten Aufruf wird dabei eine Klasse erstellt, die Methoden mit allen Befehlen enth&auml;lt, um die Datenbank und die enthaltenen Tabellen samt Feldern, Indizes und Beziehungen zu erstellen. Bei Aufrufen nach &Auml;nderungen am Entity Data Modell werden zu der jeweils neu erstellten Klasse nur Methoden mit Befehlen hinzugef&uuml;gt, die f&uuml;r das Anwenden der &Auml;nderungen notwendig sind. Die Klassen und die enthaltenen Methoden und Befehle werden durch die nachfolgend vorgestellte Anweisung angewendet.<\/li>\n<li><b>Update-Database<\/b>: Erstellt die Datenbank beziehungsweise nimmt die &Auml;nderungen vor, die durch <b>Add-Migration <\/b>hinzugef&uuml;gt wurden.<\/li>\n<\/ul>\n<h2>Beispielprojekt f&uuml;r DataAnnotations<\/h2>\n<p>Das Beispielprojekt setzen wir als WPF-App f&uuml;r das .NET Framework mit Visual Basic auf. Diesem f&uuml;gen wir ein neues Element des Typs <b>ADO.NET Entity Data Model <\/b>namens <b>DataAnnotationContext <\/b>hinzu. Im Dialog <b>Modellinhalt ausw&auml;hlen <\/b>selektieren wir <b>Leeres Code First-Modell<\/b>. Dies f&uuml;gt die Klasse <b>DataAnnotationContext.vb<\/b>, einige Verweise und Informationen &uuml;ber das Entity Framework und die Verbindungszeichenfolge zur Datei <b>App.config <\/b>hinzu. Normalerweise beziehen sich diese auf eine Datenbank, die den gleichen Namen wie das Projekt plus einem Punkt plus dem Namen der Context-Klasse hat und die mit der aktuellen SQL Server LocalDb-Instanz verwaltet wird.<\/p>\n<h2>Entit&auml;tsklassen hinzuf&uuml;gen<\/h2>\n<p>Zu Beispielzwecken ben&ouml;tigen wir die gleichen Klassen wie im oben genannten Artikel. Diese hei&szlig;en <b>Person.vb <\/b>und <b>Anrede.vb <\/b>sowie <b>Fahrzeug.vb <\/b>und <b>Ausstattungsmerkmal.vb<\/b>. Wie diese aussehen, entnehmen Sie dem Beispielprojekt, eine Beschreibung finden Sie im oben genannten Artikel. Wichtig ist: Zwischen <b>Person.vb <\/b>und <b>Anrede.vb <\/b>gibt es eine 1:n-Beziehung, zwischen <b>Fahrzeug.vb <\/b>und <b>Ausstattungsmerkmal.vb <\/b>eine m:n-Beziehung.<\/p>\n<h2>DbSet-Elemente hinzuf&uuml;gen<\/h2>\n<p>Damit der Aufruf der Anweisung <b>Add-Migration <\/b>&uuml;berhaupt Anweisungen zum Erstellen von Tabellen in eine neue Klasse schreibt, ben&ouml;tigt sie Informationen dar&uuml;ber, welche Tabellen erstellt werden sollen. Diese Information hinterlegen wir in Form von <b>DbSet<\/b>-Deklarationen in der Klasse <b>DataAnnotationContext.vb<\/b>:<\/p>\n<pre><span style=\"color:blue;\">Public <\/span>Overridable Property Anreden<span style=\"color:blue;\"> As <\/span>DbSet(Of Anrede)\r\n<span style=\"color:blue;\">Public <\/span>Overridable Property Personen<span style=\"color:blue;\"> As <\/span>DbSet(Of Person)\r\n<span style=\"color:blue;\">Public <\/span>Overridable Property Fahrzeuge<span style=\"color:blue;\"> As <\/span>DbSet(Of Fahrzeug)\r\n<span style=\"color:blue;\">Public <\/span>Overridable Property Ausstattungsmerkmale<span style=\"color:blue;\"> As <\/span>DbSet(Of Ausstattungsmerkmal)<\/pre>\n<h2>Erste Migration<\/h2>\n<p>Damit k&ouml;nnen wir die erste Migration durchf&uuml;hren und rufen die Befehle <b>Enable-Migrations <\/b>(erstellt den Ordner <b>Migrations <\/b>mit der Datei <b>Configuration.vb<\/b>) und <b>Add-Migration init <\/b>auf. Anschlie&szlig;end erstellen wir mit <b>Update-Database <\/b>eine Datenbank auf Basis der in der soeben erstellten Datei, deren Dateiname auf <b>_init.vb <\/b>endet. Wenn Sie mit dem Men&uuml;befehl <b>Ansicht|SQL Server-Objekt-Explorer <\/b>den Bereich <b>SQL Server-Objekt-Explorer <\/b>aktivieren, k&ouml;nnen Sie hier eine Verbindung mit der in der Verbindungszeichenfolge angegebenen SQL Server-Instanz herstellen und sich die Datenbank mit ihren Tabellen anzeigen lassen. Diese zeigt nicht nur die vier Tabellen f&uuml;r die von uns hinzugef&uuml;gten Entit&auml;tsklassen an, sondern auch noch eine Verkn&uuml;pfungstabelle zum Herstellen der Beziehung zwischen den beiden Klassen <b>Fahrzeug <\/b>und <b>Ausstattungsmerkmal<\/b>.<\/p>\n<h2>Datenbank neu erstellen<\/h2>\n<p>Wenn Sie die Datenbank neu erstellen wollen, sind vor dem Migrieren zwei Schritte n&ouml;tig:<\/p>\n<ul>\n<li>L&ouml;schen der Datenbank <\/li>\n<li>L&ouml;schen der Dateien im Verzeichnis <b>Migrations <\/b>mit Ausnahme von <b>Configuration.vb<\/b><\/li>\n<\/ul>\n<h2>Konventionen f&uuml;r das Erstellen\/Mapping vom Entity Data Model zum Datenmodell<\/h2>\n<p>Entity Framework nutzt hier einige Konventionen, um das Entity Data Model in ein Datenmodell umzusetzen. Diese lauten:<\/p>\n<ul>\n<li>Entity Framework erstellt die Datenbank standardm&auml;&szlig;ig in das Schema <b>dbo<\/b>.<\/li>\n<li>Tabellennamen leitet Entity Framework aus dem Namen der Entit&auml;tsklasse ab und h&auml;ngt standardm&auml;&szlig;ig noch ein <b>s <\/b>an. Das ist bei Verwendung englischer Klassennamen meist funktional, weil so aus <b>Customer <\/b>der Tabellenname <b>Customers <\/b>wird. Bei einer deutschen Bezeichnung wie <b>Kunde <\/b>wird <b>Kundes <\/b>daraus, was normalerweise nicht gew&uuml;nscht sein d&uuml;rfte. Interessant: Aus der Klasse <b>Person <\/b>erstellt Entity Framework eine Tabelle namens <b>People<\/b>.<\/li>\n<li>Prim&auml;rschl&uuml;ssel w&auml;hlt Entity Framework nach der Feldbezeichnung aus. Ist ein Feld namens <b>ID <\/b>vorhanden oder ein Feld, dessen Name sich aus der Klassenbezeichnung plus <b>ID <\/b>zusammensetzt, verwendet Entity Framework dieses als Prim&auml;rschl&uuml;sselfeld.<\/li>\n<li>Fremdschl&uuml;sselfelder ermittelt Entity Framework, indem es die Prim&auml;rschl&uuml;sseleigenschaft f&uuml;r die verkn&uuml;pfte Entit&auml;t ermittelt, also zum Beispiel <b>AnredeID<\/b>, und dann in der Klasse mit der Fremdschl&uuml;sseleigenschaft nach einer gleichnamigen Eigenschaft sucht. Findet es hier eine Eigenschaft namens <b>AnredeID<\/b>, nutzt es diese zum Erstellen des Fremdschl&uuml;sselfeldes. Falls nicht, erstellt es ein neues Fremdschl&uuml;sselfeld, dessen Bezeichnung sich aus dem Namen der zu verkn&uuml;pfenden Entit&auml;t, einem Unterstrich und <b>ID <\/b>zusammensetzt, hier also <b>Anrede_ID<\/b>.<\/li>\n<li>NULL-Werte legt Entity Framework f&uuml;r Eigenschaften des Typs <b>String <\/b>an. Zahlen- und Datumsfelder werden im Tabellenentwurf so angelegt, dass sie nicht NULL sein d&uuml;rfen.<\/li>\n<li>Die Reihenfolge der Felder in den erstellten Tabellen entspricht der Reihenfolge der Eigenschaften der Entit&auml;tsklassen. Allein die Prim&auml;rschl&uuml;sselfelder landen ganz oben.<\/li>\n<li>Entity Framework sieht automatisch die L&ouml;schweitergabe f&uuml;r alle Beziehungen vor, wenn das Fremdschl&uuml;sselfeld als <b>Required <\/b>markiert ist.<\/li>\n<\/ul>\n<h2>Mapping der Datentypen<\/h2>\n<div class=\"rcp_restricted\"><p><span style=\"color: #ff0000;\">M&ouml;chten Sie weiterlesen? Dann l&ouml;sen Sie Ihr Ticket!<\/span><br \/>\n<span style=\"color: #ff0000;\">Hier geht es zur Bestellung des Jahresabonnements des Magazins <strong>Visual Basic Entwickler<\/strong>:<\/span><br \/>\n<span style=\"color: #ff0000;\"><a style=\"color: #ff0000;\" href=\"https:\/\/shop.minhorst.com\/magazine\/363\/visual-basic-entwickler-jahresabonnement?c=77\">Zur Bestellung ...<\/a><\/span><br \/>\n<span style=\"color: #ff0000;\">Danach greifen Sie sofort auf <strong>alle rund 200 Artikel<\/strong> unseres Angebots zu - auch auf diesen hier!<\/span><br \/>\n<span style=\"color: #000000;\">Oder haben Sie bereits Zugangsdaten? Dann loggen Sie sich gleich hier ein:<\/span><\/p>\n<\/div>\n\n\t\n\t<form id=\"rcp_login_form\"  class=\"rcp_form\" method=\"POST\" action=\"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000253\/\">\n\n\t\t\n\t\t<fieldset class=\"rcp_login_data\">\n\t\t\t<p>\n\t\t\t\t<label for=\"rcp_user_login\">Username or Email<\/label>\n\t\t\t\t<input name=\"rcp_user_login\" id=\"rcp_user_login\" class=\"required\" type=\"text\"\/>\n\t\t\t<\/p>\n\t\t\t<p>\n\t\t\t\t<label for=\"rcp_user_pass\">Password<\/label>\n\t\t\t\t<input name=\"rcp_user_pass\" id=\"rcp_user_pass\" class=\"required\" type=\"password\"\/>\n\t\t\t<\/p>\n\t\t\t\t\t\t<p>\n\t\t\t\t<input type=\"checkbox\" name=\"rcp_user_remember\" id=\"rcp_user_remember\" value=\"1\"\/>\n\t\t\t\t<label for=\"rcp_user_remember\">Remember me<\/label>\n\t\t\t<\/p>\n\t\t\t<p class=\"rcp_lost_password\"><a href=\"\/data\/wp\/v2\/posts\/55000253?rcp_action=lostpassword\"><\/a><\/p>\n\t\t\t<p>\n\t\t\t\t<input type=\"hidden\" name=\"rcp_action\" value=\"login\"\/>\n\t\t\t\t<input type=\"hidden\" name=\"rcp_redirect\" value=\"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000253\/\"\/>\n\t\t\t\t<input type=\"hidden\" name=\"rcp_login_nonce\" value=\"59d9b39540\"\/>\n\t\t\t\t<input id=\"rcp_login_submit\" class=\"rcp-button\" type=\"submit\" value=\"Login\"\/>\n\t\t\t<\/p>\n\t\t\t\t\t<\/fieldset>\n\n\t\t\n\t<\/form>\n<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Wenn Sie ein Code First-Entity Data Model entwerfen, gibt es bestimmte Konventionen, die standardm&auml;&szlig;ig greifen. So hei&szlig;en Entit&auml;ten wie der Singular der zugrunde liegenden Tabellennamen oder der Prim&auml;r- und Fremdschl&uuml;ssel werden aus Feldern abgeleitet, welche die Zeichenkette ID enthalten &#8211; gegebenenfalls kombiniert mit dem Entit&auml;tsnamen. Wenn Sie mit einem Datenmodell daherkommen, dessen Tabellen das Pr&auml;fix &#8220;tbl&#8221; mitbringen, wollen Sie dieses nicht in den Entit&auml;tsnamen wiederfinden und gegebenenfalls m&ouml;chten (oder m&uuml;ssen) Sie auch noch Feldnamen &auml;ndern und diese anschlie&szlig;end mappen. Eine M&ouml;glichkeit dazu bieten die DataAnnotations, die wir in diesem Artikel beschreiben.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[66012021,662021,44000021],"tags":[],"yst_prominent_words":[],"class_list":["post-55000253","post","type-post","status-publish","format-standard","hentry","category-66012021","category-662021","category-Entity_Framework"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000253","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/comments?post=55000253"}],"version-history":[{"count":0,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000253\/revisions"}],"wp:attachment":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/media?parent=55000253"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/categories?post=55000253"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/tags?post=55000253"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/yst_prominent_words?post=55000253"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}