{"id":55001381,"date":"2022-08-01T00:00:00","date_gmt":"2022-08-04T18:13:36","guid":{"rendered":"http:\/\/access-im-unternehmen.aix-dev.de\/aiu\/?p=1381"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-30T00:00:00","slug":"Rechnungsverwaltung_Beispieldaten","status":"publish","type":"post","link":"https:\/\/access-im-unternehmen.de\/Rechnungsverwaltung_Beispieldaten\/","title":{"rendered":"Rechnungsverwaltung: Beispieldaten"},"content":{"rendered":"<p><b>Nachdem wir im Beitrag &#8222;Rechnungsverwaltung: Datenmodell&#8220; das Datenmodell f&uuml;r die Rechnungsverwaltung definiert haben, k&ouml;nnten wir eigentlich zur Programmierung der f&uuml;r die Dateneingabe ben&ouml;tigten Formulare &uuml;bergehen. Allerdings macht die Programmierung von Formularen deutlich mehr Spa&szlig;, wenn bereits einige Beispieldaten vorliegen und man direkt damit ausprobieren kann, ob die Formulare funktionieren. Als Hilfsmittel zum Erstellen der Beispieldaten verwenden wir das im Beitrag &#8222;Beispieldaten generieren mit .NET und Bogus&#8220; vorgestellte Werkzeug.<\/b><\/p>\n<h2>Vorbereitungen<\/h2>\n<p>Im Beitrag <b>Datenzugriff mit .NET, LINQPad und LINQ to DB <\/b>(<b>www.access-im-unternehmen.de\/****<\/b>) finden Sie alles, was Sie ben&ouml;tigen, um die Datenbank, die Sie mit Beispieldaten f&uuml;llen wollen, von LINQPad aus zu referenzieren.<\/p>\n<p>Im Beitrag <b>Beispieldaten generieren mit .NET und Bogus <\/b>(<b>www.access-im-unternehmen.de\/****<\/b>) finden Sie zus&auml;tzlich ausf&uuml;hrliche Hinweise darauf, wie Sie die f&uuml;r die Verwendung des Tools <b>Bogus<\/b> notwendigen Schritte durchf&uuml;hren.<\/p>\n<p>Deshalb hier nur noch einmal in aller K&uuml;rze die notwendigen Schritte:<\/p>\n<ul>\n<li>Installieren Sie das Tool <b>LINQPad<\/b>, mit dem Sie die vielen Bibliotheken nutzen k&ouml;nnen, die nur &uuml;ber .NET, aber nicht &uuml;ber VBA verf&uuml;gbar sind.<\/li>\n<li>Installieren Sie <b>LINQ to DB<\/b> in <b>LINQPad<\/b>.<\/li>\n<li>F&uuml;gen Sie eine Verbindung zu der Datenbank hinzu, die Sie mit Beispieldaten f&uuml;llen wollen. Sie sollten die Verbindungseigenschaften beispielsweise wie in Bild 1 ausf&uuml;llen.<\/li>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2022_04\/pic_1381_001.png\" alt=\"Verbindungseigenschaften f&uuml;r die Datenbank\" width=\"524,559\" height=\"691,9091\"\/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 1: Verbindungseigenschaften f&uuml;r die Datenbank<\/span><\/b><\/p>\n<li>Danach sollte LINQPad die Tabellen wie in Bild 2 anzeigen.<\/li>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2022_04\/pic_1381_002.png\" alt=\"Die verf&uuml;gbaren Tabellen\" width=\"424,5589\" height=\"480,205\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 2: Die verf&uuml;gbaren Tabellen<\/span><\/b><\/p>\n<li>Damit k&ouml;nnen Sie eine neue Query zu LINQPad hinzuf&uuml;gen, was Sie &uuml;ber den Registerreiter mit dem <b>+<\/b>-Zeichen erledigen. Speichern Sie die Query unter dem Namen <b>Rechnungsbericht_Beispieldaten<\/b>.<\/li>\n<li>W&auml;hlen Sie unter <b>Connection <\/b>die soeben hinzugef&uuml;gte Verbindung aus.<\/li>\n<li>Legen Sie unter <b>Language <\/b>den Wert <b>VB Program <\/b>fest.<\/li>\n<li>F&uuml;gen Sie wie im Beitrag  <b>Beispieldaten generieren mit .NET und Bogus <\/b>(<b>www.access-im-unternehmen.de\/****<\/b>) beschrieben die Elemente hinzu, die f&uuml;r den Einsatz von Bogus notwendig sind.<\/li>\n<\/ul>\n<h2>Vorhandene Daten l&ouml;schen<\/h2>\n<p>Wir wollen immer, wenn wir die Anwendung ausprobieren, einen frischen Satz von Daten bereitstellen. Eventuell bei einem vorherigen Test ge&auml;nderte, hinzugef&uuml;gte oder gel&ouml;schte Daten wollen wir wieder in den Urzustand versetzen &#8211; damit erm&ouml;glichen wir auch das automatisierte Testen von Teilen der Anwendung. Zum L&ouml;schen der Daten verwenden wir die Prozedur aus Listing 1. Diese rufen wir von der automatisch beim Hinzuf&uuml;gen der Query bereitgestellten Methode Main aus auf:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>DatenLoeschen\r\n     <span style=\"color:blue;\">Dim <\/span>objUserQuery<span style=\"color:blue;\"> As <\/span>UserQuery\r\n     objUserQuery = tblAnreden.DataContext\r\n     objUserQuery.Execute(\"DELETE FROM tblBestellpositionen\")\r\n     objUserQuery.Execute(\"DELETE FROM tblBestellungen\")\r\n     objUserQuery.Execute(\"DELETE FROM tblKunden\")\r\n     objUserQuery.Execute(\"DELETE FROM tblProdukte\")\r\n     objUserQuery.Execute(\"DELETE FROM tblAnreden\")\r\n     objUserQuery.Execute(\"DELETE FROM tblEinheiten\")\r\n     objUserQuery.Execute(\"DELETE FROM tblMehrwertsteuersaetze\")\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 1: L&ouml;schen der Daten<\/span><\/b><\/p>\n<pre><span style=\"color:blue;\">Sub <\/span>Main\r\n     DatenLoeschen\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Die Prozedur <b>DatenLoeschen <\/b>definiert das <b>UserQuery<\/b>-Objekt, &uuml;ber das wir auf die einzelnen Tabellen der Datenbank zugreifen k&ouml;nnen. Hier rufen wir f&uuml;r jede Tabelle einmal die <b>Execute<\/b>-Methode auf und &uuml;bergeben jeweils eine <b>DELETE<\/b>-Abfrage, mit der wir die Daten der jeweiligen Tabelle l&ouml;schen. Dies erledigen wir gleich f&uuml;r alle Tabellen der Datenbank, und zwar in einer Reihenfolge, in der zuerst die Daten aus den Tabellen gel&ouml;scht werden, die &uuml;ber Fremdschl&uuml;sselfelder mit anderen Tabellen verkn&uuml;pft sind. Die Tabelle <b>tblBestellpositionen <\/b>ist gleich &uuml;ber zwei Fremdschl&uuml;sselfelder mit den Tabellen <b>tblBestellungen <\/b>und <b>tblProdukte <\/b>verkn&uuml;pft, sodass wir diese zuerst leeren.<\/p>\n<p>Danach folgt die Tabelle <b>tblBestellungen<\/b>, die mit der Tabelle <b>tblKunden <\/b>verkn&uuml;pft ist. Die Tabelle <b>tblKunden <\/b>ist wiederum mit den Datens&auml;tzen der Tabelle <b>tblAnreden <\/b>verkn&uuml;pft und wird als n&auml;chstes gel&ouml;scht. Die Tabelle <b>tblProdukte <\/b>greift auf Daten aus den Tabellen <b>tblEinheiten <\/b>und <b>tblMehrwertsteuersaetze <\/b>zu und muss folglich vor diesen Tabellen geleert werden. Wenn wir f&uuml;r die Beziehungen die L&ouml;schweitergabe definiert h&auml;tten, k&ouml;nnten wir die L&ouml;schvorg&auml;nge andersherum steuern und w&uuml;rden auch weniger <b>DELETE<\/b>-Anweisungen brauchen, weil ja die Inhalte verkn&uuml;pfter Tabellen direkt mit gel&ouml;scht werden.<\/p>\n<p>Anschlie&szlig;end beginnen wir damit, einige der Tabellen erneut zu f&uuml;llen. Am einfachsten geht das mit den Tabellen, f&uuml;r die wir keine Zufallsdaten generieren m&uuml;ssen, sondern die wir direkt mit den gew&uuml;nschten Daten f&uuml;llen.<\/p>\n<p>Da w&auml;re als Erstes die Tabelle <b>tblAnreden<\/b>, die wir mit den bekannten Anreden f&uuml;llen. Die dazu notwendige Prozedur finden Sie in Listing 2.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>AnredenAnlegen\r\n     <span style=\"color:blue;\">Dim <\/span>objUserQuery<span style=\"color:blue;\"> As <\/span>UserQuery\r\n     objUserQuery = tblAnreden.DataContext\r\n     objUserQuery.Insert(<span style=\"color:blue;\">New<\/span> tblAnreden <span style=\"color:blue;\">With<\/span> {.ID = 1, .Anredebezeichnung = \"Herr\"})\r\n     objUserQuery.Insert(<span style=\"color:blue;\">New<\/span> tblAnreden <span style=\"color:blue;\">With<\/span> {.ID = 2, .Anredebezeichnung = \"Frau\"})\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 2: Anlegen der Anreden<\/span><\/b><\/p>\n<p>Auf &auml;hnliche Weise f&uuml;llen wir die Tabelle <b>tblEinheiten<\/b>, und zwar mit der Prozedur <b>EinheitenAnlegen <\/b>(siehe Listing 3). <\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>EinheitenAnlegen\r\n     <span style=\"color:blue;\">Dim <\/span>objUserQuery<span style=\"color:blue;\"> As <\/span>UserQuery\r\n     objUserQuery = tblEinheiten.DataContext\r\n     objUserQuery.Insert(<span style=\"color:blue;\">New<\/span> tblEinheiten <span style=\"color:blue;\">With<\/span> {.ID = 1, .Einheitbezeichnung = \"St&uuml;ck\"})\r\n     objUserQuery.Insert(<span style=\"color:blue;\">New<\/span> tblEinheiten <span style=\"color:blue;\">With<\/span> {.ID = 2, .Einheitbezeichnung = \"Stunde\"})\r\n     objUserQuery.Insert(<span style=\"color:blue;\">New<\/span> tblEinheiten <span style=\"color:blue;\">With<\/span> {.ID = 3, .Einheitbezeichnung = \"Pauschal\"})\r\n     objUserQuery.Insert(<span style=\"color:blue;\">New<\/span> tblEinheiten <span style=\"color:blue;\">With<\/span> {.ID = 4, .Einheitbezeichnung = \"Kilo\"})\r\n     objUserQuery.Insert(<span style=\"color:blue;\">New<\/span> tblEinheiten <span style=\"color:blue;\">With<\/span> {.ID = 5, .Einheitbezeichnung = \"Liter\"})\r\n     objUserQuery.Insert(<span style=\"color:blue;\">New<\/span> tblEinheiten <span style=\"color:blue;\">With<\/span> {.ID = 6, .Einheitbezeichnung = \"Meter\"})\r\n     objUserQuery.Insert(<span style=\"color:blue;\">New<\/span> tblEinheiten <span style=\"color:blue;\">With<\/span> {.ID = 7, .Einheitbezeichnung = \"Abonnement\"})\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 3: Anlegen der Einheiten<\/span><\/b><\/p>\n<p>Und auch die Tabelle <b>tblMehrwertsteuersaetze<\/b> f&uuml;llen wir nach diesem Schema (siehe Listing 4).<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>MehrwertsteuersaetzeAnlegen\r\n     <span style=\"color:blue;\">Dim <\/span>objUserQuery<span style=\"color:blue;\"> As <\/span>UserQuery\r\n     objUserQuery = tblMehrwertsteuersaetze.DataContext\r\n     objUserQuery.Insert(<span style=\"color:blue;\">New<\/span> tblMehrwertsteuersaetze <span style=\"color:blue;\">With<\/span> {.ID = 1, .Mehrwertsteuersatzbezeichnung = _\r\n         \"Erm&auml;&szlig;igter Mehrwertsteuersatz\", .Mehrwertsteuersatzwert = 0,07})\r\n     objUserQuery.Insert(<span style=\"color:blue;\">New<\/span> tblMehrwertsteuersaetze <span style=\"color:blue;\">With<\/span> {.ID = 2, .Mehrwertsteuersatzbezeichnung = _\r\n         \"Regelsteuersatz\", .Mehrwertsteuersatzwert = 0,19})\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 4: Anlegen der Mehrwertsteuers&auml;tze<\/span><\/b><\/p>\n<p>Damit geht es nun an die wirklich interessanten Daten &#8211; n&auml;mlich die, welche wir mit dem Zufallsgenerator erstellen lassen. In welcher Reihenfolge gehen wir mit den &uuml;brigen Tabellen nun vor? Wir beginnen mit den Tabellen, die nur mit den bisher gef&uuml;llten Tabellen verkn&uuml;pft sind. Hier bieten sich zun&auml;chst die Tabellen <b>tblProdukte <\/b>und <b>tblKunden <\/b>an.<\/p>\n<h2>Produkte per Zufallsgenerator f&uuml;llen<\/h2>\n<p>Als N&auml;chstes wollen wir also die Tabelle <b>tblProdukte <\/b>mit einigen Datens&auml;tzen f&uuml;llen. Wir h&auml;tten gern 100 verschiedene Produkte, also f&uuml;gen wir schon einmal den Aufruf der noch zu definierenden Prozedur <b>ProdukteAnlegen <\/b>mit dem Wert <b>100 <\/b>als Parameter zur Methode <b>Main <\/b>hinzu:<\/p>\n<pre><span style=\"color:blue;\">Sub <\/span>Main\r\n     DatenLoeschen\r\n     AnredenAnlegen\r\n     MehrwertsteuersaetzeAnlegen\r\n     EinheitenAnlegen\r\n     ProdukteAnlegen(100)\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Die dadurch aufgerufene Prozedur finden Sie in Listing 5. Hier finden wir als Erstes den Parameter <b>intMenge <\/b>vor, dem wir die Anzahl der zu erzeugenden Produkte &uuml;bergeben.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>ProdukteAnlegen(intMenge<span style=\"color:blue;\"> As <\/span>Int32)\r\n     <span style=\"color:blue;\">Dim <\/span>Beispielprodukt<span style=\"color:blue;\"> As <\/span><span style=\"color:blue;\">New<\/span> tblProdukte\r\n     <span style=\"color:blue;\">Dim <\/span>objUserQuery<span style=\"color:blue;\"> As <\/span>UserQuery\r\n     <span style=\"color:blue;\">Dim <\/span>i<span style=\"color:blue;\"> As <\/span>Int32\r\n     objUserQuery = tblProdukte.DataContext\r\n     <span style=\"color:blue;\">Dim <\/span>objFaker<span style=\"color:blue;\"> As <\/span><span style=\"color:blue;\">New<\/span> Bogus.Faker(Of tblProdukte)(\"de\")\r\n     objFaker.Rules(Function(f, p)\r\n         p.Produktbezeichnung = f.Commerce.ProductName\r\n         p.Einzelpreis = f.Commerce.Price(10, 100, 2)\r\n         p.EinheitID = f.PickRandom(Of tblEinheiten)(tblEinheiten).ID\r\n         p.MehrwertsteuersatzID = f.PickRandom(Of tblMehrwertsteuersaetze)(tblMehrwertsteuersaetze).ID\r\n     End Function)\r\n     For i = 1 To intMenge\r\n         Beispielprodukt = objFaker.Generate\r\n         Beispielprodukt.ID = i\r\n         <span style=\"color:blue;\">Debug.Print<\/span>(\"ID: \" & i & \" \" & Beispielprodukt.ID.ToString & \" \" & Beispielprodukt.Produktbezeichnung)\r\n         objUserQuery.Insert(Beispielprodukt)\r\n     <span style=\"color:blue;\">Next<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 5: Zufallsgesteuertes Anlegen von Produkten<\/span><\/b><\/p>\n<p>Die Prozedur greift &uuml;ber die Tabelle <b>tblProdukte <\/b>auf den <b>DataContext <\/b>der Datenbankverbindung zu. Mit einer Lambda-Funktion (eine Erl&auml;uterung w&uuml;rde den Rahmen sprengen) definieren wir die Regeln f&uuml;r das Anlegen der Beispieldaten. Als Produktbezeichnung w&auml;hlen wir die Eigenschaft <b>ProduktName <\/b>der Klasse <b>Commerce<\/b>. F&uuml;r den Preis nutzen wir die Eigenschaft <b>Price <\/b>der gleichen Klasse und geben hier den kleinsten und den gr&ouml;&szlig;ten m&ouml;glichen Preis an sowie die Anzahl der Nachkommastellen. Wir erhalten hiermit Preise zwischen 10 und 100 EUR mit zwei Nachkommastellen.<\/p>\n<p>Dann folgen die interessanten Elemente, n&auml;mlich die zuf&auml;llige Auswahl von Eintr&auml;gen der Tabelle <b>tblEinheiten<\/b>. Dies erreichen wir mit der Funktion <b>PickRandom<\/b>, der wir den Typ der Klasse mit den gew&uuml;nschten Daten &uuml;bergeben und f&uuml;r die wir anschlie&szlig;end einen Verweis auf die zu verwendende Auflistung <b>tblEinheiten <\/b>&uuml;bergeben. Von dem jeweils gew&auml;hlten Element m&ouml;chten wir dem Feld <b>Einheit <\/b>des neuen Produkts die Eigenschaft <b>ID <\/b>der Tabelle <b>tblEinheiten <\/b>zuweisen.<\/p>\n<p>Anschlie&szlig;end durchl&auml;uft die Prozedur eine <b>For&#8230;Next<\/b>-Schleife &uuml;ber die mit dem Parameter <b>intMenge <\/b>angegebene Anzahl von Elementen. Darin erstellen wir mit der <b>Generate<\/b>-Methode des <b>Faker<\/b>-Objekts ein neues Element und weisen seiner Eigenschaft <b>ID <\/b>den Wert der Laufvariablen zu. Anschlie&szlig;end geben wir zur Pr&uuml;fung noch ein paar Eigenschaften aus, bevor wir das Element mit der <b>Insert<\/b>-Methode zur Tabelle <b>tblProdukte <\/b>hinzuf&uuml;gen.<\/p>\n<h2>Fehlermeldung beim Hinzuf&uuml;gen von Produkten<\/h2>\n<p><!--30percent--><\/p>\n<p>Nun wollen wir den Code ausprobieren, um die Produkte hinzuzuf&uuml;gen. Dazu ist es wie immer wichtig, dass die Datenbank geschlossen ist. Anderenfalls kann LINQPad nicht schreibend auf die enthaltenen Tabellen zugreifen.<\/p>\n<p>Beim Aufrufen der Methode <b>Main <\/b>beispielsweise mit der Taste <b>F5 <\/b>erhalten wir jedoch den Fehler aus Bild 3. Allerdings tritt dieser Fehler nicht immer auf, und er passiert meist nach einer scheinbar willk&uuml;rlich angelegten Anzahl von Produktdatens&auml;tzen. <\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2022_04\/pic_1381_003.png\" alt=\"Fehlermeldung beim Hinzuf&uuml;gen von Produkten\" width=\"700\" height=\"458,9125\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 3: Fehlermeldung beim Hinzuf&uuml;gen von Produkten<\/span><\/b><\/p>\n<p>Die Fehlermeldung weist darauf hin, dass ein eindeutiger Schl&uuml;ssel verletzt wurde, also dass wir versuchen, einen bereits vorhandenen Wert nochmals in ein Feld mit einem eindeutigen Index einzuf&uuml;gen. Leider erhalten wir keinen Hinweis, um welches Feld es sich handelt. Also k&ouml;nnen wir nur selbst nachsehen und m&uuml;ssten dazu eigentlich die Datenbank &ouml;ffnen &#8211; was nach sich ziehen w&uuml;rde, dass wir auch den Zugriff auf die Datenbank via LINQPad unterbrechen m&uuml;ssen, was am zuverl&auml;ssigsten geschieht, indem wir LINQPad schlie&szlig;en.<\/p>\n<p>Allerdings haben wir bereits eine <b>Debug.Print<\/b>-Anweisung hinterlegt, welche die ID und den Produktnamen des anzulegenden Datensatzes ausgibt. Hier finden wir schnell heraus, dass es nicht an der ID liegt, sondern am Produktnamen &#8211; Bogus liefert schlicht keine eindeutigen Produktnamen und so kommt es fr&uuml;her oder sp&auml;ter (oder auch mal gar nicht) dazu, dass ein Produktname doppelt angelegt wird.<\/p>\n<h2>Fehlerbehandlung mit Try&#8230;Catch<\/h2>\n<p>Die performanteste M&ouml;glichkeit, dies zu umgehen, ist das Ignorieren des Fehlers und das erneute Schreiben eines Produktdatensatzes im Fehlerfall. Dazu f&uuml;gen wir eine <b>Try&#8230;Catch<\/b>-Anweisung zur Schleife hinzu, die wie in Listing 6 aussieht. Wir f&uuml;gen die <b>Insert<\/b>-Methode in den <b>Try<\/b>-Block ein. Tritt hier ein Fehler auf, wird der <b>Catch<\/b>-Block ausgef&uuml;hrt.<\/p>\n<pre>For i = 1 To intMenge\r\n     Beispielprodukt = objFaker.Generate\r\n     Beispielprodukt.ID = i\r\n     <span style=\"color:blue;\">Debug.Print<\/span>(\"ID: \" & i & \" \" & Beispielprodukt.ID.ToString & \" \" & Beispielprodukt.Produktbezeichnung)\r\n     Try\r\n         objUserQuery.Insert(Beispielprodukt)\r\n     Catch e<span style=\"color:blue;\"> As <\/span>Exception\r\n         <span style=\"color:blue;\">Debug.Print<\/span>(\"Fehler: \" & e.Message)    \r\n         i = i - 1\r\n     End Try\r\n<span style=\"color:blue;\">Next<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 6: Erweiterung um eine Fehlerbehandlung<\/span><\/b><\/p>\n<p>In diesem Block geben wir, nur zur Information, die Fehlermeldung im Direktbereich von LINQPad aus. Au&szlig;erdem setzen wir <b>i <\/b>um <b>1 <\/b>zur&uuml;ck, damit die Prozedur einen neuen Anlauf starten kann, einen eindeutigen Produktnamen zu finden.<\/p>\n<p>Wir k&ouml;nnten an dieser Stelle auch jeweils pr&uuml;fen, ob der neu ermittelte Produktname bereits vorhanden ist, aber dies w&uuml;rde mit wachsender Anzahl vorhandener Produkte immer mehr Zeit in Anspruch nehmen. Die Methode mit <b>Try&#8230;Catch <\/b>scheint die performantere M&ouml;glichkeit zu sein.<\/p>\n<h2>Ergebnis in der Tabelle tblProdukte pr&uuml;fen<\/h2>\n<p>Schlie&szlig;en wir nun LINQPad und &ouml;ffnen wir die Tabelle <b>tblProdukte <\/b>der Datenbank, finden wir die gew&uuml;nschten 100 Datens&auml;tze in der Tabelle <b>tblProdukte<\/b> vor (siehe Bild 4).<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2022_04\/pic_1381_004.png\" alt=\"Die Tabelle tblProdukte mit Beispieldaten\" width=\"549,559\" height=\"474,0318\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 4: Die Tabelle tblProdukte mit Beispieldaten<\/span><\/b><\/p>\n<h2>Kundendaten anlegen<\/h2>\n<p>Als N&auml;chstes folgen die Kundendaten. Auch f&uuml;r diese legen wir eine neue Prozedur an, die wir diesmal <b>KundenAnlegen <\/b>nennen (siehe Listing 7). Auch diese Prozedur erh&auml;lt einen Parameter, der wieder <b>intMenge<\/b> hei&szlig;t und die Anzahl der zu erstellenden Kundendatens&auml;tze entgegennimmt.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>KundenAnlegen(intMenge<span style=\"color:blue;\"> As <\/span>Int32)\r\n     <span style=\"color:blue;\">Dim <\/span>Beispielkunde<span style=\"color:blue;\"> As <\/span><span style=\"color:blue;\">New<\/span> tblKunden\r\n     <span style=\"color:blue;\">Dim <\/span>objUserQuery<span style=\"color:blue;\"> As <\/span>UserQuery\r\n     <span style=\"color:blue;\">Dim <\/span>i<span style=\"color:blue;\"> As <\/span>Int32\r\n     <span style=\"color:blue;\">Dim <\/span>intGender<span style=\"color:blue;\"> As <\/span>int32\r\n     objUserQuery = tblKunden.DataContext\r\n     <span style=\"color:blue;\">Dim <\/span>objFaker<span style=\"color:blue;\"> As <\/span><span style=\"color:blue;\">New<\/span> Bogus.Faker(Of tblKunden)(\"de\")\r\n     objFaker.Rules(Function(f, k)\r\n         intGender = f.PickRandom(Of Gender)\r\n         k.kundennummer = 99000000 + i\r\n         k.Firma = f.Company.CompanyName\r\n         k.AnredeID = intGender + 1\r\n         k.Vorname = f.Name.FirstName(intGender)\r\n         k.Nachname = f.Name.LastName()\r\n         k.Strasse = f.Address.StreetAddress\r\n         k.PLZ = f.Address.ZipCode\r\n         k.Ort = f.Address.City\r\n         k.LandID = 1\r\n         k.UstIDNr = \"DE\" & f.Random.Number(100000000, 999999999)\r\n         k.EMail = f.Internet.Email\r\n     End Function)\r\n     For i = 1 To intMenge\r\n         Beispielkunde = objFaker.Generate\r\n         Beispielkunde.ID = i\r\n         objUserQuery.Insert(Beispielkunde)\r\n     <span style=\"color:blue;\">Next<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 7: Anlegen von Kundendaten<\/span><\/b><\/p>\n<p>Diesmal haben wir keine Probleme wegen der Verletzung eindeutiger Indizes zu erwarten, da in der Tabelle <b>tblKunden <\/b>neben dem Prim&auml;rschl&uuml;sselfeld <b>ID<\/b> keine Felder mit eindeutigem Schl&uuml;ssel versehen sind. Man k&ouml;nnte sich &uuml;berlegen, ob man eines f&uuml;r die Firma vorsieht, aber es kann durchaus sein, dass es mehrere Kunden mit der gleichen Firmenadresse gibt. Und da es selbst mehrere Michael M&uuml;ller in der gleichen Firma geben kann (die Firma muss nur gro&szlig; genug sein), lassen wir den eindeutigen Index einfach weg.<\/p>\n<p>Wir legen wieder mithilfe der Lambda-Funktion <b>Function(f, k) <\/b>eine Vorlage an, mit der wir in der anschlie&szlig;enden <b>For&#8230;Next<\/b>-Schleife die Datens&auml;tze der Tabelle <b>tblKunden <\/b>f&uuml;llen.<\/p>\n<p>Damit wir die Anrede und den Vornamen passend zum jeweiligen Geschlecht ermitteln k&ouml;nnen, definieren wir die folgende Enumeration:<\/p>\n<pre><span style=\"color:blue;\">Public <\/span>Enum Gender\r\n     Male = 0\r\n     Female = 1\r\nEnd Enum<\/pre>\n<p>So ermitteln wir in der Vorlage als Erstes mit <b>PickRandom(Of Gender) <\/b>einen der beiden Werte dieser Enumeration und speichern diesen in der Variablen <b>intGender<\/b>. Dann ermitteln wir die Kundennummer, die sich aus der Summe aus <b>99000000 <\/b>und dem Index <b>i <\/b>zusammensetzt &#8211; f&uuml;r den ersten Kunden also beispielsweise <b>99000001<\/b>.<\/p>\n<p>Danach ermitteln wir den Namen der <b>Firma <\/b>&uuml;ber die Eigenschaft <b>CompanyName <\/b>der Klasse <b>Company<\/b>.<\/p>\n<p>Erst dann kommen wir zur Anrede und zum Vornamen. Wir wissen, dass die beiden Datens&auml;tze <b>Herr <\/b>und <b>Frau <\/b>in der Tabelle <b>tblAnreden <\/b>die Werte <b>1 <\/b>und <b>2 <\/b>als Prim&auml;rschl&uuml;sselwert verwenden. Daher k&ouml;nnen wir den Wert des Fremdschl&uuml;sselfeldes <b>AnredeID <\/b>mit <b>intGender + 1 <\/b>f&uuml;llen.<\/p>\n<p>Den Vornamen ermitteln wir mit der Eigenschaft <b>FirstName <\/b>der Klasse <b>Name<\/b>, der wir <b>intGender <\/b>&uuml;bergeben, also einen der Werte der Enumeration <b>Gender<\/b>. Die Eigenschaft liefert entsprechend einen m&auml;nnlichen oder einen weiblichen Namen zur&uuml;ck.<\/p>\n<h2>Weitere Adressdaten<\/h2>\n<p>Den Nachnamen ermitteln wir mit <b>Name.LastName<\/b>, die Adressdaten mit <b>Address.StreetAddress<\/b>, <b>Address.ZipCode <\/b>und <b>Address.City<\/b>. Schlie&szlig;lich stellen wir das Feld <b>LandID <\/b>f&uuml;r alle Datens&auml;tze auf den statischen Wert <b>1 <\/b>ein (f&uuml;r <b>Deutschland<\/b>).<\/p>\n<h2>Umsatzsteuer-Identifikationsnummer per Zufall<\/h2>\n<p>Von der Umsatzsteuer-Identifikationsnummer wissen wir, dass diese f&uuml;r deutsche Unternehmen mit DE beginnen und aus neun weiteren Ziffern bestehen. Also nehmen wir <b>DE <\/b>als statischen Teil und f&uuml;gen dann eine Zufallszahl zwischen <b>100.000.000 <\/b>und <b>999.999.999 <\/b>hinzu, sodass beispielsweise DE123456789 herauskommt.<\/p>\n<p>Die E-Mail liefert hingegen die Eigenschaft <b>Email <\/b>der Klasse <b>Internet<\/b>. Damit sind auch alle Felder definiert und wir k&ouml;nnen uns dem eigentlichen Erstellen zuwenden. In der Schleife erstellen wir mit der <b>Generate<\/b>-Methode jeweils ein neues Element und weisen diesem f&uuml;r das Prim&auml;rschl&uuml;sselfeld <b>ID <\/b>den Wert der Z&auml;hlervariablen <b>i <\/b>der Schleife zu. Schlie&szlig;lich f&uuml;gen wir den neuen Kunden mit der Insert-Methode zur Tabelle <b>tblKunden <\/b>hinzu. Die Tabelle sieht nach dem Hinzuf&uuml;gen von 100 Kunden wie in Bild 5 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2022_04\/pic_1381_005.png\" alt=\"Frisch erstellte Kundendatens&auml;tze\" width=\"700\" height=\"310,1961\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 5: Frisch erstellte Kundendatens&auml;tze<\/span><\/b><\/p>\n<h2>Bestellungen anlegen<\/h2>\n<p>Damit gehen wir direkt zur Tabelle <b>tblBestellungen <\/b>&uuml;ber. Hier nutzen wir wieder den Parameter <b>intMenge<\/b>, um die Anzahl der anzulegenden Bestellungen einzustellen (siehe Listing 8).<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>BestellungenAnlegen(intMenge<span style=\"color:blue;\"> As <\/span>Int32)\r\n     <span style=\"color:blue;\">Dim <\/span>Beispielbestellung<span style=\"color:blue;\"> As <\/span><span style=\"color:blue;\">New<\/span> tblBestellungen\r\n     <span style=\"color:blue;\">Dim <\/span>objUserQuery<span style=\"color:blue;\"> As <\/span>UserQuery\r\n     <span style=\"color:blue;\">Dim <\/span>i<span style=\"color:blue;\"> As <\/span>Int32\r\n     <span style=\"color:blue;\">Dim <\/span>bolNichtStorniert<span style=\"color:blue;\"> As Boolean<\/span>\r\n     <span style=\"color:blue;\">Dim <\/span>bolBezahlt<span style=\"color:blue;\"> As Boolean<\/span>\r\n     objUserQuery = tblBestellungen.DataContext\r\n     <span style=\"color:blue;\">Dim <\/span>objFaker<span style=\"color:blue;\"> As <\/span><span style=\"color:blue;\">New<\/span> Bogus.Faker(Of tblBestellungen)(\"de\")\r\n     objFaker.Rules(Function(f, b)\r\n     b.KundeID = f.PickRandom(Of tblKunden)(tblKunden).ID\r\n     b.Bestellnummer = 11000000 + i\r\n     b.BestelltAm = f.Date.Past(1, DateTime.Now)\r\n     bolNichtStorniert = f.Random.Bool(0.85)\r\n     <span style=\"color:blue;\">If <\/span>bolNichtStorniert<span style=\"color:blue;\"> Then<\/span>\r\n         b.RechnungAm = Microsoft.VisualBasic.DateAndTime.DateAdd(\"d\", f.Random.Number(1, 10), b.BestelltAm)\r\n         b.Zahlungsziel = Microsoft.VisualBasic.DateAndTime.DateAdd(\"d\", 21, b.RechnungAm)\r\n         bolBezahlt = f.Random.Bool(0.9)\r\n         <span style=\"color:blue;\">If <\/span>bolBezahlt<span style=\"color:blue;\"> Then<\/span>\r\n             b.BezahltAm = Microsoft.VisualBasic.DateAndTime.DateAdd(\"d\", f.Random.Number(1, 10), b.RechnungAm)\r\n         End if\r\n     <span style=\"color:blue;\">Else<\/span>\r\n         b.StorniertAm = Microsoft.VisualBasic.DateAndTime.DateAdd(\"d\", f.Random.Number(1, 10), b.BestelltAm)\r\n     <span style=\"color:blue;\">End If<\/span>\r\n     End Function)\r\n     For i = 1 To intMenge\r\n         Beispielbestellung = objFaker.Generate\r\n         Beispielbestellung.ID = i\r\n         objUserQuery.Insert(Beispielbestellung)\r\n     <span style=\"color:blue;\">Next<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 8: Anlegen von Bestelldaten <\/span><\/b><\/p>\n<p>Der Aufruf in der Methode <b>Main <\/b>lautet diesmal:<\/p>\n<pre>BestellungenAnlegen(300)<\/pre>\n<p>Beim Zusammenstellen der Vorlage f&uuml;r das Erstellen der Bestellungen ermitteln wir zun&auml;chst mit <b>f.PickRandom(Of tblKunden)(tblKunden).ID <\/b>zuf&auml;llig einen Kunden und weisen diesen dem Fremdschl&uuml;sselfeld <b>KundeID <\/b>zu.<\/p>\n<p>Die Bestellnummer entspricht der Summe von <b>11.000.000 <\/b>plus <b>i<\/b>, also beispielsweise <b>11000123<\/b>. Das Bestelldatum ermitteln wir mit der <b>Past<\/b>-Eigenschaft der <b>Date<\/b>-Klasse, wobei wir zuf&auml;llig Werte im Zeitraum von vor einem Jahr bis heute ermitteln.<\/p>\n<p>Danach ermitteln wir f&uuml;r die <b>Boolean<\/b>-Variable <b>bolNichtStorniert<\/b>, ob die aktuelle Bestellung als storniert eingetragen werden soll. Dazu nutzen wir den Ausdruck <b>f.Random.Bool(0.85)<\/b>, der zu 85% den Wert <b>True <\/b>liefert. Wurde die Bestellung nicht storniert, legen wir das Rechnungsdatum fest (zwischen <b>1 <\/b>und <b>10 <\/b>Tage nach dem Bestelldatum) sowie das Zahlungsziel (21 Tage nach dem Rechnungsdatum). Hier nutzen wir die <b>DateAdd<\/b>-Methode der Klasse <b>DateAndTime <\/b>des Namespaces <b>Microsoft.VisualBasic<\/b>.<\/p>\n<p>Ein paar Kunden bezahlen ihre Rechnung nicht, also legen wir nur f&uuml;r die Rechnungen, die bezahlt wurden, einen Wert im Feld <b>BezahltAm <\/b>fest.<\/p>\n<p>Hat <b>bolNichtStorniert <\/b>den Wert <b>False<\/b>, legen wir einen Wert f&uuml;r das Feld <b>StorniertAm <\/b>fest.<\/p>\n<p>Schlie&szlig;lich tragen wir die Datens&auml;tze auf Basis dieser Vorlage mit der <b>Generate<\/b>-Methode in die Tabelle <b>tblBestellungen <\/b>ein. Die Tabelle <b>tblBestellungen<\/b> sieht anschlie&szlig;end wie in Bild 6 aus.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2022_04\/pic_1381_006.png\" alt=\"Neue Bestellungen, die teilweise storniert oder nicht bezahlt wurden\" width=\"700\" height=\"364,8523\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 6: Neue Bestellungen, die teilweise storniert oder nicht bezahlt wurden<\/span><\/b><\/p>\n<h2>Bestellpositionen hinzuf&uuml;gen<\/h2>\n<p>Schlie&szlig;lich fehlen nur noch die Bestellpositionen (siehe Listing 9). Die Prozedur <b>BestellpositionenAnlegen <\/b>erwartet die folgenden Parameter:<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>BestellpositionenAnlegen(intPositionenMin<span style=\"color:blue;\"> As <\/span>Int32, intPositionenMax<span style=\"color:blue;\"> As <\/span>Int32, intMengeMin<span style=\"color:blue;\"> As <\/span>Int32, _\r\n         intMengeMax<span style=\"color:blue;\"> As <\/span>int32)\r\n     <span style=\"color:blue;\">Dim <\/span>Beispielbestellposition<span style=\"color:blue;\"> As <\/span><span style=\"color:blue;\">New<\/span> tblBestellpositionen\r\n     <span style=\"color:blue;\">Dim <\/span>objUserQuery<span style=\"color:blue;\"> As <\/span>UserQuery\r\n     <span style=\"color:blue;\">Dim <\/span>objProdukt AS tblProdukte\r\n     <span style=\"color:blue;\">Dim <\/span>lngMehrwertsteuersatzID<span style=\"color:blue;\"> As <\/span>int32\r\n     <span style=\"color:blue;\">Dim <\/span>objMehrwertsteuersatz<span style=\"color:blue;\"> As <\/span>tblMehrwertsteuersaetze\r\n     <span style=\"color:blue;\">Dim <\/span>i<span style=\"color:blue;\"> As <\/span>Int32\r\n     <span style=\"color:blue;\">Dim <\/span>j<span style=\"color:blue;\"> As <\/span>int32\r\n     <span style=\"color:blue;\">Dim <\/span>k<span style=\"color:blue;\"> As <\/span>int32\r\n     <span style=\"color:blue;\">Dim <\/span>intPositionen<span style=\"color:blue;\"> As <\/span>Int32\r\n     objUserQuery = tblBestellpositionen.DataContext\r\n     <span style=\"color:blue;\">Dim <\/span>objFaker<span style=\"color:blue;\"> As <\/span><span style=\"color:blue;\">New<\/span> Bogus.Faker(Of tblBestellpositionen)(\"de\")\r\n     objFaker.Rules(Function(f, b)\r\n                        objProdukt = f.PickRandom(Of tblProdukte)(tblProdukte)\r\n                        b.ProduktID = objProdukt.ID\r\n                        b.Menge = f.Random.Int(intMengeMin, intMengeMax)\r\n                        b.Einzelpreis = objProdukt.Einzelpreis\r\n                        lngMehrwertsteuersatzID = objProdukt.MehrwertsteuersatzID\r\n                        objMehrwertsteuersatz = tblMehrwertsteuersaetze.First(Function(m) m.ID = lngMehrwertsteuersatzID)\r\n                        b.Mehrwertsteuersatz = objMehrwertsteuersatz.Mehrwertsteuersatzwert\r\n                        b.EinheitID = objProdukt.EinheitID\r\n                        b.Rabatt = f.PickRandomParam(0,0,0,0,0,5,5,10,15)\r\n                        intPositionen = f.Random.Int(intPositionenMin, intPositionenMax)\r\n                    End Function)\r\n     For i = 1 To tblBestellungen.Count\r\n         Beispielbestellposition = objFaker.Generate\r\n         For j = 1 To intPositionen\r\n             Beispielbestellposition = objFaker.Generate\r\n             k = k + 1\r\n             Beispielbestellposition.ID = k\r\n             Beispielbestellposition.BestellungID = tblBestellungen.ElementAt(i-1).ID\r\n             Try\r\n                 objUserQuery.Insert(Beispielbestellposition)\r\n             Catch\r\n                 k = k - 1\r\n                 j = j - 1\r\n             End Try\r\n         <span style=\"color:blue;\">Next<\/span> j\r\n     <span style=\"color:blue;\">Next<\/span>\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 9: Anlegen von Bestellpositionen<\/span><\/b><\/p>\n<ul>\n<li><b>intPositionenMin<\/b>: Mindestanzahl der Positionen<\/li>\n<li><b>intPositionenMax<\/b>: Maximale Anzahl der Positionen<\/li>\n<li><b>intMengeMin<\/b>: Mindestmenge je Position<\/li>\n<li><b>intMengeMax<\/b>: Maximale Menge je Position<\/li>\n<\/ul>\n<p>In der Lambda-Funktion zum Definieren der Vorlage f&uuml;r einen Datensatz der Tabelle <b>tblBestellpositionen <\/b>ermitteln wir zun&auml;chst zuf&auml;llig einen Datensatz aus der Tabelle <b>tblProdukte<\/b>.<\/p>\n<p>Das Produkt referenzieren wir dabei noch mit der Variablen <b>objProdukt<\/b>, da wir noch auf weitere Eigenschaften dieses Datensatzes zugreifen wollen. Hier lesen wir zun&auml;chst den Wert des Prim&auml;rschl&uuml;sselfeldes <b>ID <\/b>aus und tragen diesen f&uuml;r das Fremdschl&uuml;sselwertfeld <b>ProduktID <\/b>ein. F&uuml;r das Feld <b>Menge <\/b>tragen wir einen Wert zwischen <b>intMengeMin <\/b>und <b>intMengeMax <\/b>ein, den wir mit der Funktion <b>Int <\/b>der Klasse <b>Random <\/b>ermitteln.<\/p>\n<p>Den Einzelpreis f&uuml;gen einfach aus dem Produkt in das Feld <b>Einzelpreis <\/b>ein. Etwas komplizierter ist der Mehrwertsteuersatz. Dieser ist &uuml;ber das Fremdschl&uuml;sselfeld <b>MehrwertsteuersatzID <\/b>festgelegt worden und wir m&uuml;ssen den dazugeh&ouml;rigen Mehrwertsteuersatz auslesen. Also ermitteln wir erst einmal den Fremdschl&uuml;sselwert aus dem Feld <b>MehrwertsteuersatzID <\/b>aus und speichern ihn in der Variablen <b>lngMehrwertsteuersatzID<\/b>. Diesen nutzen wir dazu, das Element aus der Tabelle <b>tblMehrwertsteuersaetze<\/b> zu ermitteln und mit der Variable <b>objMehrwertsteuersatz <\/b>zu referenzieren. Daraus lesen wir den Wert des Feldes <b>Mehrwertsteuersatz <\/b>aus und tragen ihn in das Feld <b>Mehrwertsteuersatz <\/b>der Bestellposition ein. F&uuml;r die Einheit tragen wir einfach den Wert des Feldes <b>EinheitID <\/b>in das gleichnamige Feld der Bestellposition ein.<\/p>\n<p>Spannend wird das Feld <b>Rabatt<\/b>. Da keine Werte f&uuml;r dieses Feld in irgendeiner Tabelle vorliegen, nutzen wir die Funktion <b>PickRandomParam <\/b>aus. Diese erm&ouml;glicht es, mehrere Werte anzugeben, aus denen zuf&auml;llig einer ausgew&auml;hlt wird. Unsere Parameterliste lautet 0,0,0,0,0,5,5,10,15. Alle Werte werden mit der gleichen Wahrscheinlichkeit ausgew&auml;hlt. Da wir beispielsweise f&uuml;nf Mal den Wert <b>0 <\/b>angegeben haben und vier andere Werte, wird mit einer Wahrscheinlichkeit von <b>5\/9 <\/b>der Wert <b>0 <\/b>gew&auml;hlt.<\/p>\n<p>Schlie&szlig;lich tragen wir in <b>intPositionen <\/b>noch die Anzahl der Positionen f&uuml;r die jeweilige Bestellung ein. Die minimale und maximale Anzahl &uuml;bergeben wir mit den Parametern <b>intPositionenMin <\/b>und <b>intPositionenMax<\/b>.<\/p>\n<p>Danach folgt die erste von zwei <b>For&#8230;Next<\/b>-Schleifen, mit der wir die Werte von <b>1 <\/b>bis zur Anzahl der f&uuml;r die Tabelle <b>tblBestellungen <\/b>angelegten Datens&auml;tze durchlaufen &#8211; in diesem Fall also <b>300<\/b>. Die Schleife enth&auml;lt neben einer weiteren <b>For&#8230;Next<\/b>-Schleife nur eine Anweisung, in der wir mithilfe von <b>objFaker.Generate <\/b>die Variable <b>intPositionen <\/b>f&uuml;llen. Diese nutzen wir f&uuml;r die zweite <b>For&#8230;Next<\/b>-Schleife, die von <b>1 <\/b>bis zur Anzahl der Positionen dieser Bestellung aus <b>intPositionen <\/b>l&auml;uft. Hier rufen wir <b>objFaker.Generate <\/b>erneut auf und erh&ouml;hen eine Laufvariable namens <b>k<\/b>, die als Grundlage f&uuml;r die Prim&auml;rschl&uuml;sselwerte der Bestellpositionen dient, jeweils um <b>1<\/b>. <\/p>\n<p>Den Wert von <b>k <\/b>weisen wir dem Prim&auml;rschl&uuml;sselfeld <b>ID <\/b>der aktuelle Bestellposition zu. Danach ermitteln wir den Prim&auml;rschl&uuml;sselwert der Bestellung, die wir gerade mit Bestellpositionen f&uuml;llen. Dazu nutzen wir die Tabelle <b>tblBestellungen <\/b>und ermitteln das Element mit dem Index <b>i-1<\/b>. Dessen <b>ID <\/b>lesen wir aus und f&uuml;gen den Wert dem Fremdschl&uuml;sselfeld <b>BestellungID <\/b>der Bestellposition hinzu.<\/p>\n<p>Nun folgt wieder ein <b>Try&#8230;Catch<\/b>-Konstrukt, in dessen <b>Try<\/b>-Teil wir versuchen, die neue Bestellposition zu speichern. Das kann mit recht geringer Wahrscheinlichkeit fehlschlagen, n&auml;mlich dann, wenn ein Produkt zum zweiten Mal einer Bestellung hinzugef&uuml;gt werden soll.<\/p>\n<p>Dann sorgt eine Verletzung des eindeutigen, zusammengesetzten Schl&uuml;ssels der beiden Fremdschl&uuml;sselfelder <b>BestellungID <\/b>und <b>ProduktID <\/b>daf&uuml;r, dass eine Ausnahme ausgel&ouml;st wird. In diesem Fall stellen wir einfach <b>k <\/b>und <b>i <\/b>um <b>1 <\/b>zur&uuml;ck und versuchen es mit einem anderen Produkt. Auf diese Weise stellen wir die Daten f&uuml;r die Tabelle <b>tblBestellpositionen <\/b>wie in Bild 7 zusammen.<\/p>\n<p class=\"image\"><img decoding=\"async\" src=\"..\/fileadmin\/_temp_\/2022_04\/pic_1381_007.png\" alt=\"Per Zufallsgenerator angelegte Bestellpositionen\" width=\"674,559\" height=\"486,1298\" \/><\/p>\n<p><b><span style=\"color:darkgrey;\">Bild 7: Per Zufallsgenerator angelegte Bestellpositionen<\/span><\/b><\/p>\n<h2>Schreiben der Daten f&uuml;r alle Tabellen<\/h2>\n<p>Die Methode <b>Main<\/b> zum Aufruf aller hier vorgestellten Prozeduren sieht nun wie folgt aus:<\/p>\n<pre><span style=\"color:blue;\">Sub <\/span>Main\r\n     DatenLoeschen\r\n     AnredenAnlegen\r\n     MehrwertsteuersaetzeAnlegen\r\n     EinheitenAnlegen\r\n     ProdukteAnlegen(100)\r\n     KundenAnlegen(100)\r\n     BestellungenAnlegen(300)\r\n     BestellpositionenAnlegen(1, 5, 1, 10)\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p>Sie k&ouml;nnen die Zahlen in den Prozeduren <b>ProdukteAnlegen<\/b>, <b>KundenAnlegen<\/b>, <b>BestellungenAnlegen <\/b>und <b>BestellpositionenAnlegen <\/b>beliebig variieren. Vielleicht haben Sie auch nur wenige Produkte, die Sie auf viele Bestellungen aufteilen wollen und die Produkte sollen nicht zuf&auml;llig hinzugef&uuml;gt werden, sondern nach spezifischen Daten.<\/p>\n<p>Dann w&uuml;rden Sie die Prozedur <b>ProdukteAnlegen <\/b>beispielsweise wie in Listing 10 anpassen.<\/p>\n<pre><span style=\"color:blue;\">Public Sub <\/span>ProdukteAnlegen\r\n     <span style=\"color:blue;\">Dim <\/span>objUserQuery<span style=\"color:blue;\"> As <\/span>UserQuery\r\n     objUserQuery = tblProdukte.DataContext\r\n     objUserQuery.Insert(<span style=\"color:blue;\">New<\/span> tblProdukte <span style=\"color:blue;\">With<\/span> {.ID = 1, .Produktbezeichnung = \"Access im Unternehmen\", _\r\n         .EinheitID = 7, .Einzelpreis = 159, .MehrwertsteuersatzID = 1})\r\n     objUserQuery.Insert(<span style=\"color:blue;\">New<\/span> tblProdukte <span style=\"color:blue;\">With<\/span> {.ID = 2, .Produktbezeichnung = \"Anwendungen entwickeln mit Access\", _\r\n         .EinheitID = 1, .Einzelpreis = 69, .MehrwertsteuersatzID = 1})\r\n     objUserQuery.Insert(<span style=\"color:blue;\">New<\/span> tblProdukte <span style=\"color:blue;\">With<\/span> {.ID = 3, .Produktbezeichnung = \"Access und SQL Server\",  _\r\n         .EinheitID = 1, .Einzelpreis = 69, .MehrwertsteuersatzID = 1})\r\n     objUserQuery.Insert(<span style=\"color:blue;\">New<\/span> tblProdukte <span style=\"color:blue;\">With<\/span> {.ID = 4, .Produktbezeichnung = \"Access und Office\", .EinheitID = 1,  _\r\n         .Einzelpreis = 69, .MehrwertsteuersatzID = 1})\r\n     objUserQuery.Insert(<span style=\"color:blue;\">New<\/span> tblProdukte <span style=\"color:blue;\">With<\/span> {.ID = 5, .Produktbezeichnung = \"Onlinebanking mit Access\",  _\r\n         .EinheitID = 1, .Einzelpreis = 69, .MehrwertsteuersatzID = 1})\r\n     objUserQuery.Insert(<span style=\"color:blue;\">New<\/span> tblProdukte <span style=\"color:blue;\">With<\/span> {.ID = 6, .Produktbezeichnung = \"Access [basics]\", .EinheitID = 7,  _\r\n         .Einzelpreis = 69, .MehrwertsteuersatzID = 1})\r\n     objUserQuery.Insert(<span style=\"color:blue;\">New<\/span> tblProdukte <span style=\"color:blue;\">With<\/span> {.ID =76, .Produktbezeichnung = \"Datenbankentwickler\",  _\r\n         .EinheitID = 7, .Einzelpreis = 129, .MehrwertsteuersatzID = 1})\r\n<span style=\"color:blue;\">End Sub<\/span><\/pre>\n<p><b><span style=\"color:darkgrey;\">Listing 10: Anlegen von Produkten <\/span><\/b><\/p>\n<h2>Downloads zu diesem Beitrag<\/h2>\n<p>Enthaltene Beispieldateien:<\/p>\n<p>Rechnungsbericht_Beispieldaten.accdb<\/p>\n<p>Rechnungsbericht_Beispieldaten.linq<\/p>\n<p><a href=\"..\/fileadmin\/beispiele\/232FBE59-A19C-4BEF-9992-56F6192BE891\/aiu_1381.zip\">Download<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Nachdem wir im Beitrag &#8222;Rechnungsverwaltung: Datenmodell&#8220; das Datenmodell f&uuml;r die Rechnungsverwaltung definiert haben, k&ouml;nnten wir eigentlich zur Programmierung der f&uuml;r die Dateneingabe ben&ouml;tigten Formulare &uuml;bergehen. Allerdings macht die Programmierung von Formularen deutlich mehr Spa&szlig;, wenn bereits einige Beispieldaten vorliegen und man direkt damit ausprobieren kann, ob die Formulare funktionieren. Als Hilfsmittel zum Erstellen der Beispieldaten verwenden wir das im Beitrag &#8222;Beispieldaten generieren mit .NET und Bogus&#8220; vorgestellte Werkzeug.<\/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":[662022,66042022,44000021],"tags":[],"class_list":["post-55001381","post","type-post","status-publish","format-standard","hentry","category-662022","category-66042022","category-Tabellen_und_Datenmodellierung"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.9 (Yoast SEO v27.4) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Rechnungsverwaltung: Beispieldaten - Access im Unternehmen<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/access-im-unternehmen.de\/Rechnungsverwaltung_Beispieldaten\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Rechnungsverwaltung: Beispieldaten\" \/>\n<meta property=\"og:description\" content=\"Nachdem wir im Beitrag &quot;Rechnungsverwaltung: Datenmodell&quot; das Datenmodell f&uuml;r die Rechnungsverwaltung definiert haben, k&ouml;nnten wir eigentlich zur Programmierung der f&uuml;r die Dateneingabe ben&ouml;tigten Formulare &uuml;bergehen. Allerdings macht die Programmierung von Formularen deutlich mehr Spa&szlig;, wenn bereits einige Beispieldaten vorliegen und man direkt damit ausprobieren kann, ob die Formulare funktionieren. Als Hilfsmittel zum Erstellen der Beispieldaten verwenden wir das im Beitrag &quot;Beispieldaten generieren mit .NET und Bogus&quot; vorgestellte Werkzeug.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/access-im-unternehmen.de\/Rechnungsverwaltung_Beispieldaten\/\" \/>\n<meta property=\"og:site_name\" content=\"Access im Unternehmen\" \/>\n<meta property=\"article:published_time\" content=\"2022-08-04T18:13:36+00:00\" \/>\n<meta name=\"author\" content=\"Andr\u00e9 Minhorst\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Andr\u00e9 Minhorst\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"20\u00a0Minuten\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Rechnungsverwaltung_Beispieldaten\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Rechnungsverwaltung_Beispieldaten\\\/\"},\"author\":{\"name\":\"Andr\u00e9 Minhorst\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\"},\"headline\":\"Rechnungsverwaltung: Beispieldaten\",\"datePublished\":\"2022-08-04T18:13:36+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Rechnungsverwaltung_Beispieldaten\\\/\"},\"wordCount\":3186,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"articleSection\":[\"2022\",\"4\\\/2022\",\"Tabellen und Datenmodellierung\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Rechnungsverwaltung_Beispieldaten\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Rechnungsverwaltung_Beispieldaten\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Rechnungsverwaltung_Beispieldaten\\\/\",\"name\":\"Rechnungsverwaltung: Beispieldaten - Access im Unternehmen\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\"},\"datePublished\":\"2022-08-04T18:13:36+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Rechnungsverwaltung_Beispieldaten\\\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/access-im-unternehmen.de\\\/Rechnungsverwaltung_Beispieldaten\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/Rechnungsverwaltung_Beispieldaten\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Rechnungsverwaltung: Beispieldaten\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#website\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\",\"name\":\"Access im Unternehmen\",\"description\":\"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Microsoft Access\",\"publisher\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/access-im-unternehmen.de\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"de\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#organization\",\"name\":\"Andr\u00e9 Minhorst Verlag\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/access-im-unternehmen.de\\\/wp-content\\\/uploads\\\/2019\\\/09\\\/aiu_wp.png\",\"contentUrl\":\"https:\\\/\\\/access-im-unternehmen.de\\\/wp-content\\\/uploads\\\/2019\\\/09\\\/aiu_wp.png\",\"width\":370,\"height\":111,\"caption\":\"Andr\u00e9 Minhorst Verlag\"},\"image\":{\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/access-im-unternehmen.de\\\/#\\\/schema\\\/person\\\/13395c4bcd7d7963efe33be9c584d93f\",\"name\":\"Andr\u00e9 Minhorst\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g\",\"caption\":\"Andr\u00e9 Minhorst\"}}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Rechnungsverwaltung: Beispieldaten - Access im Unternehmen","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/access-im-unternehmen.de\/Rechnungsverwaltung_Beispieldaten\/","og_locale":"de_DE","og_type":"article","og_title":"Rechnungsverwaltung: Beispieldaten","og_description":"Nachdem wir im Beitrag \"Rechnungsverwaltung: Datenmodell\" das Datenmodell f&uuml;r die Rechnungsverwaltung definiert haben, k&ouml;nnten wir eigentlich zur Programmierung der f&uuml;r die Dateneingabe ben&ouml;tigten Formulare &uuml;bergehen. Allerdings macht die Programmierung von Formularen deutlich mehr Spa&szlig;, wenn bereits einige Beispieldaten vorliegen und man direkt damit ausprobieren kann, ob die Formulare funktionieren. Als Hilfsmittel zum Erstellen der Beispieldaten verwenden wir das im Beitrag \"Beispieldaten generieren mit .NET und Bogus\" vorgestellte Werkzeug.","og_url":"https:\/\/access-im-unternehmen.de\/Rechnungsverwaltung_Beispieldaten\/","og_site_name":"Access im Unternehmen","article_published_time":"2022-08-04T18:13:36+00:00","author":"Andr\u00e9 Minhorst","twitter_card":"summary_large_image","twitter_misc":{"Verfasst von":"Andr\u00e9 Minhorst","Gesch\u00e4tzte Lesezeit":"20\u00a0Minuten"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/access-im-unternehmen.de\/Rechnungsverwaltung_Beispieldaten\/#article","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/Rechnungsverwaltung_Beispieldaten\/"},"author":{"name":"Andr\u00e9 Minhorst","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f"},"headline":"Rechnungsverwaltung: Beispieldaten","datePublished":"2022-08-04T18:13:36+00:00","mainEntityOfPage":{"@id":"https:\/\/access-im-unternehmen.de\/Rechnungsverwaltung_Beispieldaten\/"},"wordCount":3186,"commentCount":0,"publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"articleSection":["2022","4\/2022","Tabellen und Datenmodellierung"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/access-im-unternehmen.de\/Rechnungsverwaltung_Beispieldaten\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/access-im-unternehmen.de\/Rechnungsverwaltung_Beispieldaten\/","url":"https:\/\/access-im-unternehmen.de\/Rechnungsverwaltung_Beispieldaten\/","name":"Rechnungsverwaltung: Beispieldaten - Access im Unternehmen","isPartOf":{"@id":"https:\/\/access-im-unternehmen.de\/#website"},"datePublished":"2022-08-04T18:13:36+00:00","breadcrumb":{"@id":"https:\/\/access-im-unternehmen.de\/Rechnungsverwaltung_Beispieldaten\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/access-im-unternehmen.de\/Rechnungsverwaltung_Beispieldaten\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/access-im-unternehmen.de\/Rechnungsverwaltung_Beispieldaten\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/access-im-unternehmen.de\/"},{"@type":"ListItem","position":2,"name":"Rechnungsverwaltung: Beispieldaten"}]},{"@type":"WebSite","@id":"https:\/\/access-im-unternehmen.de\/#website","url":"https:\/\/access-im-unternehmen.de\/","name":"Access im Unternehmen","description":"Das Magazin f\u00fcr Datenbankentwickler auf Basis von Microsoft Access","publisher":{"@id":"https:\/\/access-im-unternehmen.de\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/access-im-unternehmen.de\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Organization","@id":"https:\/\/access-im-unternehmen.de\/#organization","name":"Andr\u00e9 Minhorst Verlag","url":"https:\/\/access-im-unternehmen.de\/","logo":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/logo\/image\/","url":"https:\/\/access-im-unternehmen.de\/wp-content\/uploads\/2019\/09\/aiu_wp.png","contentUrl":"https:\/\/access-im-unternehmen.de\/wp-content\/uploads\/2019\/09\/aiu_wp.png","width":370,"height":111,"caption":"Andr\u00e9 Minhorst Verlag"},"image":{"@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/access-im-unternehmen.de\/#\/schema\/person\/13395c4bcd7d7963efe33be9c584d93f","name":"Andr\u00e9 Minhorst","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/1b9d010cf1716692cb9c34f21554e07d17d461acaea5b61b8cb21cbec678d48a?s=96&d=mm&r=g","caption":"Andr\u00e9 Minhorst"}}]}},"_links":{"self":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55001381","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/comments?post=55001381"}],"version-history":[{"count":0,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/posts\/55001381\/revisions"}],"wp:attachment":[{"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/media?parent=55001381"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/categories?post=55001381"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/access-im-unternehmen.de\/data\/wp\/v2\/tags?post=55001381"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}