{"id":55000144,"date":"2018-08-01T00:00:00","date_gmt":"2020-03-27T19:33:39","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=144"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"RazorPages_Daten_aus_LookupTabellen","status":"publish","type":"post","link":"https:\/\/vbentwickler.de\/RazorPages_Daten_aus_LookupTabellen\/","title":{"rendered":"Razor-Pages: Daten aus Lookup-Tabellen"},"content":{"rendered":"<p><b>Im Artikel &#8220;Razor Pages mit Datenbankanbindung&#8221; haben wir gezeigt, wie Sie Daten aus einfachen Tabellen in einer &Uuml;bersichtliste anzeigen, Details bearbeiten, neue Datens&auml;tze anlegen und vorhandene Datens&auml;tze &auml;ndern. In diesem Artikel nun wollen wir eine Lookup-Tabelle hinzunehmen, mit der wir die Anreden der Kunden aus der bereits vorhandenen Tabelle abbilden. Diese sollen dann in den Details per Nachschlagefeld ausgew&auml;hlt werden. Eine kleine Schaltfl&auml;che neben dem Nachschlagefeld soll es dann erm&ouml;glichen, die Lookup-Daten zu bearbeiten.<\/b><\/p>\n<h2>Lookup-Entit&auml;t hinzuf&uuml;gen<\/h2>\n<p>Im Artikel <b>EDM: 1:n-Beziehungen per Code First<\/b> erfahren Sie im Detail, wie Sie 1:n-Beziehungen zwischen zwei Entit&auml;ten aufbauen.<\/p>\n<p>F&uuml;r den vorliegenden Artikel wollen wir der bisher verwendeten Klasse <b>Customer <\/b>eine weitere Klasse namens <b>Salutation <\/b>hinzuf&uuml;gen, die wir dazu im Ordner <b>Models <\/b>anlegen:<\/p>\n<pre>public class Salutation {\r\n     public int ID { get; set; }\r\n     public string Name { get; set; }\r\n     public ICollection&lt;Customer&gt; Customers { get; set; }\r\n}<\/pre>\n<p>Um die Beziehung zwischen den beiden Klassen herzustellen, f&uuml;gen wir der Klasse <b>Customer <\/b>auch noch zwei Elemente hinzu:<\/p>\n<pre>public class Customer {\r\n     public int ID { get; set; }\r\n     public string FirstName { get; set; }\r\n     public string LastName { get; set; }\r\n     public string Street { get; set; }\r\n     public string Zip { get; set; }\r\n     public string City { get; set; }\r\n     public int SalutationID { get; set; }\r\n     public Salutation Salutation { get; set; }\r\n}<\/pre>\n<p>Schlie&szlig;lich f&uuml;gen wir die neue Klasse noch als <b>DbSet <\/b>zur Klasse <b>CustomerManagementContext <\/b>im Verzeichnis <b>Data <\/b>hinzu:<\/p>\n<pre>public class CustomerManagementContext : DbContext {\r\n     ...\r\n     public DbSet&lt;Customer&gt; Customers { get; set; }\r\n     public DbSet&lt;Salutation&gt; Salutations { get; set; }\r\n     ...\r\n}<\/pre>\n<p>Danach &uuml;bernehmen Sie die &Auml;nderungen durch das Absetzen der folgenden beiden Anweisungen in der Paket-Manager-Konsole in die Datenbank, die in der Verbindungszeichenfolge der Datei <b>appsettings.json <\/b>angegeben ist:<\/p>\n<pre>Add-Migration Init\r\nUpdate-Database<\/pre>\n<p>Um die Datenbank frisch anzulegen, l&ouml;schen Sie die Datenbank zuvor aus dem SQL Server-Objekt-Explorer und entfernen auch alle Eintr&auml;ge im Verzeichnis <b>Migrations <\/b>im Projektmappen-Explorer.<\/p>\n<h2>Daten hinzuf&uuml;gen<\/h2>\n<p>Und damit beim Starten der Anwendung und beim Initialisieren auch noch ein paar Daten in der Tabelle <b>Salutations <\/b>landen und das Feld <b>Salutation <\/b>der Datens&auml;tze der Tabelle <b>Customers <\/b>mit Werten aus der Tabelle <b>Salutations <\/b>gef&uuml;llt wird, passen wir auch noch die Methode <b>Initialize <\/b>in der Klasse <b>DbInitializer <\/b>an:<\/p>\n<pre>public class DbInitializer {\r\n     public static void Initialize(CustomerManagementContext dbContext) {\r\n         dbContext.Database.EnsureCreated();\r\n         if (dbContext.Customers.Any()) {\r\n             return;\r\n         }\r\n         var salutations = new Salutation[] {\r\n             new Salutation { Name = \"Herr\" },\r\n             new Salutation { Name = \"Frau\" },\r\n             new Salutation { Name = \"Firma\" }\r\n         };\r\n         foreach (Salutation s in salutations)             {\r\n             dbContext.Salutations.Add(s);\r\n         }\r\n         var customers = new Customer[] {\r\n             new Customer{FirstName=\"Andr&eacute;\", LastName=\"Minhorst\", Street=\"Borkhofer Str. 17\", Zip=\"47137\", \r\n                 City=\"Duisburg\", Salutation=salutations[0] }, ...\r\n         };\r\n         foreach (Customer c in customers) {\r\n             dbContext.Customers.Add(c);\r\n         }\r\n         dbContext.SaveChanges();\r\n     }\r\n}<\/pre>\n<p>Diese legt nun zuerst einige Anreden an, bevor die Kunden mit dem jeweiligen Verweis auf die Anrede mit dem namens <b>Herr <\/b>hinzugef&uuml;gt werden. Danach speichert die Methode die hinzugef&uuml;gten Elemente mit der <b>SaveChanges<\/b>-Methode.<\/p>\n<h2>Anzeigen der Anreden in der &Uuml;bersicht der Kunden<\/h2>\n<p>Als Erstes wollen wir die Seite <b>Pages|Customers|Index.cshtml <\/b>so anpassen, dass sie die Anrede der Kunden anzeigt. Dazu f&uuml;gen wir der Tabelle auf der Seite <b>Index.cshtml <\/b>jeweils eine Spalte zum Element <b>thead|tr <\/b>und zum Element <b>tbody|tr <\/b>hinzu. Dabei geben wir als Wert zun&auml;chst das Feld <b>SalutationID <\/b>an:<\/p>\n<pre>&lt;table class=\"table\"&gt;\r\n     &lt;thead&gt;\r\n         &lt;tr&gt;\r\n             ... andere &Uuml;berschriften ...\r\n             &lt;th&gt;\r\n                 @Html.DisplayNameFor(model =&gt; model.Customer[0].Salutation)\r\n             &lt;\/th&gt;\r\n             &lt;th&gt;&lt;\/th&gt;\r\n         &lt;\/tr&gt;\r\n     &lt;\/thead&gt;\r\n     &lt;tbody&gt;\r\n@foreach (var item in Model.Customer) {\r\n         &lt;tr&gt;\r\n             ... andere Feldinhalte ...\r\n             &lt;td&gt;\r\n                 @Html.DisplayFor(modelItem =&gt; item.SalutationID)\r\n             &lt;\/td&gt;\r\n             ...\r\n         &lt;\/tr&gt;\r\n}\r\n     &lt;\/tbody&gt;\r\n&lt;\/table&gt;<\/pre>\n<p>Die &Uuml;bersichtsseite zeigt nun eine neue Spalte mit dem Fremdschl&uuml;sselwert des Feldes <b>SalutationID<\/b> an (siehe Bild 1). Das ist zwar ein erster Schritt, aber nicht das, was wir erreichen wollen &#8211; wir m&ouml;chten ja den Wert des Feldes <b>Name<\/b> des Datensatzes der Tabelle <b>Salutations<\/b>, der mit dem aktuellen Datensatz der Tabelle <b>Customers <\/b>verkn&uuml;pft ist, anzeigen. Dazu &auml;ndern wir schlicht und einfach das Feld:<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2018_04\/pic_144_001.png\" alt=\"Ein erster Schritt - die Anzeige des Fremdschl&uuml;sselwertes\" width=\"574,61\" height=\"374,6195\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Ein erster Schritt &#8211; die Anzeige des Fremdschl&uuml;sselwertes<\/span><\/b><\/p>\n<pre>     @Html.DisplayFor(modelItem =&gt; item.Salutation.Name)\r\n&lt;\/td&gt;<\/pre>\n<p>Dies f&uuml;hrt allerdings nicht zum gew&uuml;nschten Ergebnis &#8211; auf diese Weise bleibt die Spalte schlicht leer. Auch die einfache Verwendung von <b>item.Salutation <\/b>liefert eine leere Spalte. Allerdings wird auch keine Ausnahme ausgel&ouml;st &#8211; wo liegt also das Problem Es liegt daran, dass wir nur die Daten der Tabelle <b>Customers <\/b>laden, aber nicht die der verkn&uuml;pften Tabelle <b>Salutations <\/b>&#8211; und diese beherbergt nun einmal das Feld <b>Name<\/b>, mit dem wir die Anrede in der Tabelle ausgeben wollen.<\/p>\n<p>Um diese Daten zu laden, gibt es verschiedene M&ouml;glichkeiten. Die einfachste ist diese hier, bei der wir einfach die Daten des <b>Salutation<\/b>-Elements zum jeweiligen <b>Customer<\/b>-Objekt auslesen, und zwar indem wir mit der <b>Include<\/b>-Methode arbeiten (mittlere Anweisung):<\/p>\n<pre>public async Task OnGetAsync(string firstName, string firstNamePart) {\r\n     var customers = from m in _context.Customers select m;\r\n     customers = customers.Include(c =&gt; c.Salutation);\r\n     Customer = await customers.ToListAsync();\r\n}<\/pre>\n<p>Dies liefert endlich die gew&uuml;nschten Anreden in der Auflistung der Kunden (siehe Bild 2).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2018_04\/pic_144_002.png\" alt=\"Kundenliste mit Anreden\" width=\"549,6265\" height=\"318,8908\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Kundenliste mit Anreden<\/span><\/b><\/p>\n<h2>Anrede beim Anlegen oder &Auml;ndern ausw&auml;hlen<\/h2>\n<p>Nun gehen wir einen Schritt weiter und schauen uns den Dialog zum Bearbeiten eines Kunden an. Hier wollen wir das Steuer-element f&uuml;r die Auswahl der Anrede ebenfalls integrieren.<\/p>\n<p>In diesem Fall ben&ouml;tigen wir kein einfaches Textfeld, sondern ein Auswahlfeld. Unter HTML hei&szlig;en diese Steuer-elemente <b>Select<\/b>-Felder.<\/p>\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\/55000144\/\">\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\/55000144?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\/55000144\/\"\/>\n\t\t\t\t<input type=\"hidden\" name=\"rcp_login_nonce\" value=\"123b777de9\"\/>\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>Im Artikel &#8220;Razor Pages mit Datenbankanbindung&#8221; haben wir gezeigt, wie Sie Daten aus einfachen Tabellen in einer &Uuml;bersichtliste anzeigen, Details bearbeiten, neue Datens&auml;tze anlegen und vorhandene Datens&auml;tze &auml;ndern. In diesem Artikel nun wollen wir eine Lookup-Tabelle hinzunehmen, mit der wir die Anreden der Kunden aus der bereits vorhandenen Tabelle abbilden. Diese sollen dann in den Details per Nachschlagefeld ausgew&auml;hlt werden. Eine kleine Schaltfl&auml;che neben dem Nachschlagefeld soll es dann erm&ouml;glichen, die Lookup-Daten zu bearbeiten.<\/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":[662018,66042018,44000018,44000017],"tags":[],"yst_prominent_words":[],"class_list":["post-55000144","post","type-post","status-publish","format-standard","hentry","category-662018","category-66042018","category-ASPNET_Core","category-WebApps_Razor_Pages"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000144","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=55000144"}],"version-history":[{"count":0,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000144\/revisions"}],"wp:attachment":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/media?parent=55000144"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/categories?post=55000144"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/tags?post=55000144"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/yst_prominent_words?post=55000144"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}