{"id":55000168,"date":"2019-02-01T00:00:00","date_gmt":"2020-03-27T19:36:29","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=168"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Entity_Framework_Daten_archivieren","status":"publish","type":"post","link":"https:\/\/vbentwickler.de\/Entity_Framework_Daten_archivieren\/","title":{"rendered":"Entity Framework: Daten archivieren"},"content":{"rendered":"<p><b>Im Artikel &#8220;Entity Framework: Gespeicherte Prozeduren&#8221; haben wir gezeigt, wie Sie gespeicherte Prozeduren f&uuml;r die Entit&auml;ten einer Anwendung anlegen und diese beim &Auml;ndern, Anlegen oder L&ouml;schen von Entit&auml;ten nutzen. Damit diese gespeicherten Prozeduren auch einen Mehrwert haben, zeigen wir im vorliegenden Artikel, wie Sie die gespeicherten Prozeduren so erweitern, dass Sie etwa vor dem &Auml;ndern eines Datensatzes eine Kopie dieses Datensatzes in einer f&uuml;r diesen Zweck vorgesehenen Tabelle anlegen, um sp&auml;ter die &Auml;nderungen reproduzieren und wiederherstellen zu k&ouml;nnen.<\/b><\/p>\n<h2>Voraussetzung<\/h2>\n<p>Wir starten in diesem Artikel mit dem Beispielprojekt, das wir im Beitrag Entity Framework: Gespeicherte Prozeduren erstellt haben. Dieses enth&auml;lt bereits die Entit&auml;ten unserer Bestellverwaltung und die Migrationsklassen, mit denen wir die Datenbank auf Basis der Entit&auml;ten erstellen und &uuml;ber die Seed-Methode mit Daten f&uuml;llen k&ouml;nnen. Die Aufgabe ist nun, erstens eine Tabelle namens KundenArchiv zu erstellen, in der wir die alten Kundendaten speichern k&ouml;nnen. Dabei wollen wir den verwendeten Prim&auml;rschl&uuml;sselwert des Datensatzes sichern sowie das Datum der &Auml;nderung. Danach wollen wir die gespeicherte Prozedur dbo.Kunden_Update so anpassen, dass vor dem Durchf&uuml;hren der &Auml;nderungen am Datensatz die alte Version des Datensatzes in der Tabelle dbo.Kunden_Update gespeichert wird. Au&szlig;erdem soll auch die Tabelle zum Archivieren der Daten per Update-Database erstellt werden, sodass wir entsprechenden Code in einer Migrationsklasse anlegen m&uuml;ssen.<\/p>\n<h2>Gespeicherte Prozeduren anpassen<\/h2>\n<p>Wir wollen die gespeicherten Prozedur dbo.Kunden_Update so anpassen, dass diese in einer noch zu erstellenden Tabelle namens KundenArchiv die Version der Datens&auml;tze der Tabelle Kunden vor der &Auml;nderung speichert. Dazu ben&ouml;tigen wir zun&auml;chst eine solche Tabelle. Diese legen wir mit dem folgenden Skript an, das wir in einem neuen Abfragefenster f&uuml;r die aktuelle Datenbank ausf&uuml;hren. Das Abfragefenster &ouml;ffnen wir, indem wir im SQL Server-Objekt-Explorer mit der rechten Maustaste auf den Eintrag f&uuml;r die Datenbank klicken und den Eintrag New Query&#8230; (deutsch Neue Abfrage&#8230;) bet&auml;tigen. Da wir nur wenige &Auml;nderungen gegen&uuml;ber der Originaltabelle Kunden durchf&uuml;hren wollen, k&ouml;nnen wir den Code zur Erstellung der Tabelle Kunden als Vorlage verwenden. Diesen erhalten Sie, indem Sie mit der rechten Maustaste auf die Tabelle Kunden klicken und aus dem Kontextmen&uuml; den Eintrag Skripterstellung als&#8230;|CREATE in|Neues Abfragefenster ausw&auml;hlen. Hier &auml;ndern Sie den Tabellennamen Kunden &uuml;berall in KundenArchiv. Au&szlig;erdem f&uuml;gen wir das Feld GeaendertAm hinzu, welches das &Auml;nderungsdatum speichern soll. Das zweite neue Feld hei&szlig;t OriginalID und soll die ID des Datensatzes enthalten, der ge&auml;ndert wurde:<\/p>\n<pre>CREATE TABLE [dbo].[KundenArchiv] (\r\n     [ID]          INT            IDENTITY (1, 1) NOT NULL,\r\n     [OriginalID]  INT            NOT NULL,\r\n     [Firma]       NVARCHAR (255) NULL,\r\n     [Vorname]     NVARCHAR (255) NOT NULL,\r\n     [Nachname]    NVARCHAR (255) NOT NULL,\r\n     [AnredeID]    INT            NOT NULL,\r\n     [Strasse]     NVARCHAR (255) NOT NULL,\r\n     [PLZ]         NVARCHAR (255) NOT NULL,\r\n     [Ort]         NVARCHAR (255) NOT NULL,\r\n     [Land]        NVARCHAR (255) NOT NULL,\r\n     [EMail]       NVARCHAR (255) NOT NULL,\r\n     [GeaendertAm] DATETIME       NOT NULL\r\n);\r\nGO\r\nCREATE NONCLUSTERED INDEX [IX_AnredeID]\r\n     ON [dbo].[KundenArchiv]([AnredeID] ASC);\r\nGO\r\nALTER TABLE [dbo].[KundenArchiv]\r\n     ADD CONSTRAINT [PK_dbo.KundenArchiv] PRIMARY KEY CLUSTERED ([ID] ASC);\r\nGO\r\nALTER TABLE [dbo].[KundenArchiv]\r\n     ADD CONSTRAINT [FK_dbo.KundenArchiv_dbo.Anreden_AnredeID] FOREIGN KEY ([AnredeID]) REFERENCES [dbo].[Anreden] ([ID]) ON DELETE CASCADE;<\/pre>\n<p>F&uuml;hren Sie dieses Skript aus, indem Sie auf die Starten-Schaltfl&auml;che oben im Skriptfenster klicken (nicht zu verwechseln mit der Starten-Schaltfl&auml;che f&uuml;r das Projekt in der Symbolleiste von Visual Studio). Nach der Aktualisierung des Elements Tabellen im SQL Server-Objekt-Explorer erscheint dort die neue Tabelle KundenArchiv.<\/p>\n<h2>Gespeicherte Prozedur &#8220;Kunden_Update&#8221; anpassen<\/h2>\n<p>Nun m&uuml;ssen wir die gespeicherte Prozedur dbo.Kunden_Update so anpassen, dass nicht nur die &Auml;nderungen am aktuellen Datensatz gespeichert werden, sondern zuvor noch die aktuelle Version des Datensatzes in der Tabelle KundenArchiv archiviert wird. Diese &Auml;nderung k&ouml;nnten Sie zur Migration namens StoredProcedures hinzuf&uuml;gen, sofern Sie diese noch nicht ausgef&uuml;hrt haben. Allerdings k&ouml;nnen wir auch eine neue Migration anlegen und dort unseren Code einf&uuml;gen. Dazu geben Sie einfach den folgenden Befehl in die Paketmanager-Konsole ein:<\/p>\n<pre>add-migration AlterStoredProcedure<\/pre>\n<p>Es erscheint eine leere Klasse. Diese hat wieder zwei Methoden &#8211; die Up- und die Down-Methode. Nochmal zur Verdeutlichung: Wenn Sie in der Paketmanager-Konsole Update-Database aufrufen, werden alle Up-Methoden der vorhandenen Migrationsklassen aufgerufen, die noch nicht ausgef&uuml;hrt wurden. Deshalb f&uuml;gen wir den Aufruf der Methode AlterStoredProcedure, die zum &Auml;ndern einer gespeicherten Prozedur zum Einsatz kommt, f&uuml;r die Up-Methode ein:<\/p>\n<pre><span style=\"color:blue;\">Public <\/span>Partial Class AlterStoredProcedure\r\n     Inherits DbMigration\r\n     <span style=\"color:blue;\">Public <\/span>Overrides Sub Up()\r\n         AlterStoredProcedure(\r\n             \"dbo.Kunde_Update\",\r\n             Function(p) <span style=\"color:blue;\">New<\/span> <span style=\"color:blue;\">With<\/span>\r\n                 {\r\n                     .ID = p.Int(), .Firma = p.String(maxLength:=255), .Vorname = p.String(maxLength:=255),\r\n                     .Nachname = p.String(maxLength:=255), .AnredeID = p.Int(), .Strasse = p.String(maxLength:=255),\r\n                     .PLZ = p.String(maxLength:=255), .Ort = p.String(maxLength:=255), .Land = p.String(maxLength:=255),\r\n                     .EMail = p.String(maxLength:=255)\r\n                 },\r\n             body:=\"INSERT [dbo].[KundenArchiv]([OriginalID], [Firma], [Vorname], [Nachname], [AnredeID], [Strasse], \"                 \r\n                 & \"[PLZ], [Ort], [Land], [EMail], [GeaendertAm])\" & <span style=\"color:blue;\">vbCrLf<\/span> &\r\n                 \"SELECT ID, Firma, Vorname, Nachname, AnredeID, Strasse, PLZ, Ort, Land, EMail, \" \r\n                 & \"GETDATE() AS GeaendertAm FROM Kunden WHERE ID = @ID;\" & <span style=\"color:blue;\">vbCrLf<\/span> &\r\n                 \"UPDATE [dbo].[Kunden]\" & <span style=\"color:blue;\">vbCrLf<\/span> &\r\n                 \"SET [Firma] = @Firma, [Vorname] = @Vorname, [Nachname] = @Nachname, [AnredeID] = @AnredeID, \" &\r\n                 \"[Strasse] = @Strasse, [PLZ] = @PLZ, [Ort] = @Ort, [Land] = @Land, [EMail] = @EMail\" & <span style=\"color:blue;\">vbCrLf<\/span> &\r\n                 \"WHERE ([ID] = @ID);\"\r\n         )\r\n     End Sub<\/pre>\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\/55000168\/\">\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\/55000168?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\/55000168\/\"\/>\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;Entity Framework: Gespeicherte Prozeduren&#8221; haben wir gezeigt, wie Sie gespeicherte Prozeduren f&uuml;r die Entit&auml;ten einer Anwendung anlegen und diese beim &Auml;ndern, Anlegen oder L&ouml;schen von Entit&auml;ten nutzen. Damit diese gespeicherten Prozeduren auch einen Mehrwert haben, zeigen wir im vorliegenden Artikel, wie Sie die gespeicherten Prozeduren so erweitern, dass Sie etwa vor dem &Auml;ndern eines Datensatzes eine Kopie dieses Datensatzes in einer f&uuml;r diesen Zweck vorgesehenen Tabelle anlegen, um sp&auml;ter die &Auml;nderungen reproduzieren und wiederherstellen zu k&ouml;nnen.<\/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":[66012019,662019,44000021],"tags":[],"yst_prominent_words":[],"class_list":["post-55000168","post","type-post","status-publish","format-standard","hentry","category-66012019","category-662019","category-Entity_Framework"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000168","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=55000168"}],"version-history":[{"count":0,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/posts\/55000168\/revisions"}],"wp:attachment":[{"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/media?parent=55000168"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/categories?post=55000168"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/tags?post=55000168"},{"taxonomy":"yst_prominent_words","embeddable":true,"href":"https:\/\/vbentwickler.de\/data\/wp\/v2\/yst_prominent_words?post=55000168"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}