Dieser Artikel wurde maschinell übersetzt.

Programmiererpraxis

Erste Schritte mit Eichenlaub: Datenbankinteraktion

Ted Neward

Willkommen zurück. Ich habe zu der Fuß durch Einstieg in Eiche, ein dynamisches Konzept für die Webentwicklung, die Ideen aus der Ruby und Node.js Welt verkörpert und können weiterhin die Programmiersprache c#, ASP.NET MVC Framework und den Rest der Microsoft .NET Framework Sie genießen. Das Wesen der Eiche ist "schnelle Feedback, reibungslosen Entwicklung und niedrige Zeremonie" in den Worten des Projekts Schöpfer Amir Rajan.

Wenn ich aufhörte, Eiche klagte es konnte keine Verbindung auf eine Daten-­Basis. In diesem Artikel zeige ich Ihnen, wie Sie Folgendes tun: Draht oben Eiche an einer SQL Server -Serverinstanz, die System (Kommentare Blogeinträge) eine andere verwandte Art hinzufügen, erstellen Sie die Datenbank in Eiche, beziehen sich die beiden Typen, die zusammen mit Eiche und sehen wie Eiche und seine Buildsystem Datenbank Interaktion behandelt.

Das letzte Mal Eiche lief, es tauchte eine Fehlermeldung und hilfreichen erklärenden Text, zeigt ein Auszug davon Abbildung 1. (Zur Erinnerung: Falls Sie in der letzten Spalte entlang folgten — bei msdn.microsoft.com/magazine/dn532208— müssen Sie kick-off des Servers und Sidekick Läufer.) Bevor ich viel weiter gehen, nehmen Sie zur Kenntnis wie Eiche ist nicht nur eine Ausnahmestapelüberwachung angezeigt und überlässt es mir zu entdecken oder zu recherchieren, was das Problem verursachen könnte. Es ist tatsächlich versucht, das Problem und mögliche Lösungen vorgeschlagen zu diagnostizieren: in diesem Fall "Update der Web-Config mit Ihrer Server-Instanz."

The Oak Project Help Window After an Error Is Thrown
Abbildung 1 ist das Eiche Projekt-Hilfe-Fenster nach einem Fehler ausgelöst.

Sicher genug, nahm ein kurzer Blick auf die Datei "Web.config" ich aus den "warm-up" Edelstein-Shows, die ein einfacher Platzhalter gibt Hinweis auf eine "(local)" Datenquelle, die für eine Vielzahl von Konfigurationen, je nach Konfiguration die lokale SQL Server -Serverinstanz funktionieren könnte. Das heißt, es ist so trivial, in einer LocalDB-Verbindungszeichenfolge zu löschen, wie es ist, fallen in eine entfernte SQL Server -Zeichenfolge (oder einer Windows Azure SQL-Datenbank, ist es wünschenswert, dass die Daten in der Cloud zu halten). Ich mag mit LocalDB, die ist in der Regel nur eine Verbindungszeichenfolge "Server = (Localdb) \v11.0;Integrated Security = True" für Erkundungen gefällt, denn es klein ist und relativ leicht bereinigt. Welcher SQL-Verbindung, die Sie verwenden, stecken Sie es nur in der < Konfiguration > / < ConnectionStrings > / < hinzufügen > Element und Aktualisieren der Seite. In der Tat hat die Eiche eine Rake (Ruby Build-Werkzeug) Aufgabe dazu über die Codebasis für Sie: "rake Update_db_server [(Localdb) \\v11.0]" (der umgekehrte Schrägstrich mit Escapezeichen versehen werden muss).

Äh... Houston?

Leider verhält wenn erneut ausführen, Eiche, als ob nichts geändert hat. Auch das ist leider völlig wahr. Sidekick ist nicht gerade für Änderungen an der web.config, so scheint es, nur die Quelldateien. Wenn man bedenkt, wie selten Sie die Datei "Web.config" ändern das ist nicht das Ende der Welt, aber es setzt einen kleinen Krampf in was sonst ein ziemlich mühelos Prozess ist. Um Sidekick zu erkennen, dass das Projekt geändert zu erhalten, muss man nur ein speichern einige wichtige Datei, z. B. HomeController.cs oder einige andere Quelldatei auslösen. Dies ist auf zwei Arten möglich: Wechseln Sie zu der Datei, wählen Sie einen zufälligen Ort in die Datei, drücken Sie die Leertaste und Löschen dieses Raumes, (der Visual Studio überzeugt, dass die Datei "geändert" und ein speichern zwingt) oder gerade manuell kick-off Rake von einer Eingabeaufforderung.

Sobald das erledigt ist, eine Aktualisierung des Browsers öffnet sich ein anderer Fehler ("Ungültiger Objektname"Blogs""), und du bist direkt in die Welt der Datenbankmigrationen.

Zahlen, Daten, Zahlen!

Eiche will wie seine konzeptionelle Vorgänger Verwalten von Datenbanken und Datenbankschema für Sie, damit die Datenbank vor Ihrer Ansicht mehr oder weniger "versteckt" bleiben kann. In diesem Fall Eiche will einfach nicht "automatisch" Handwerk eine Datenbank aus der Luft gegriffen, weil Sie dann wahrscheinlich einige Meinungen zum Aussehen des Schemas — und auch wenn Sie nicht, die Datenbank-Admins oft tun. (Wer gewinnt die Schlacht, oder wer sollte dieser Schlacht zu gewinnen ist eine Diskussion, die beste hatte über Biere — vorzugsweise lange, nachdem das Projekt geliefert hat.)

In Eiche, Aussaat der Datenbank erfolgt mit einem bestimmten Controller, SeedController, fand direkt neben der HomeController in SeedController.cs geschachtelt. Diese Datei enthält eine Definition für die SeedController schon, aber – vor allem für Ihre Zwecke — es enthält auch eine Schemaklasse, das erleichtert die erforderlichen Schritte zum Erstellen des Schemas und, optional, Beispieldaten eingeführt. Bedenken Sie, übrigens, das ist die Standardkonvention Eiche, dass Objekte in einer Datenbanktabelle pluralisiert Namen gespeichert werden, so dass in einer Tabelle namens Blogs Blog-Objekte gespeichert werden. ** Abbildung 2** zeigt die Schema-Klasse.

Abbildung 2 die Schemaklasse

public class Schema
{
  // This is the method you'll want to alter
  public IEnumerable<Func<dynamic>> Scripts()
  {
    // Replace all content inside of the Scripts() method with this line
    yield return CreateBlogsTable; // Return just the pointer to the function
  }
  public string CreateBlogsTable() // Here is the function definition
  {
    // This is an example, your table name may be different
    // For more information on schema generation check out the Oak wiki
    return Seed.CreateTable("Blogs",
      Seed.Id(),
      new { Name = "nvarchar(255)" },
      new { Body = "nvarchar(max)" }
    );
  }
  public void SampleEntries()
  {
  }
  public Seed Seed { get; set; }
  public Schema(Seed seed) { Seed = seed; }
}

Beachten Sie das seltsame "Yield return" in der Skripts-Methode. Für diejenigen unter euch, die nicht herausfinden konnte, dies in c# 2.0 Tat, "Yield return" erstellt einen anonymen "Stream" von Objekten und Hände wieder eine IEnumerable < T > auf diesen Stream zeigen. In diesem speziellen Fall es ist ein Strom von Funktionen, und in diesem speziellen Szenario ist es einen Stream einer Funktion (CreateBlogsTable). Im Wesentlichen sind Sie einen Strom von Aktionen (Func < dynamisch > Einrichten Instanzen) darstellt, wie zum Erstellen der Datenbank und Eiche werden jede Aktion oder Funktion gab zurück aus diesem stream und ausführen kann. Auf diese Weise, wenn eine neue Änderung des Schemas ins Spiel kommt, dass der Wandel in eine neue Funktion erfasst werden kann ("CreateComments­Tabelle," Wenn man so will) und einfach in die Liste aufgenommen. Falls gewünscht, könntest du "Version" des Datenbankschemas durch Aufrufen der ersten Funktion Version1, die zweite Version2 und so weiter. Das Eiche Wiki hat weitere Informationen über Datenbankmigrationen bei bit.ly/1bgods5.

(Für diejenigen, die meine "Multiparadigmatic.NET" Serie erinnern, die beginnt bei msdn.microsoft.com/magazine/ff955611, ja, dies ist ein ziemlich funktional ausgerichteten Weg der Annäherung an dieses Problem.)

Die Seed.Id-Funktion erstellt die kanonische Primärschlüsselspalte: ein Auto-Inkrement-Integer-Wert gekennzeichnet als Primärschlüssel. Das Eiche Wiki (bit.ly/1iKfcIb) enthält eine Referenz zum Erstellen einer Datenbank mit der Seed-Klasse zu tun, aber es gibt immer die ad-hoc-Fallback gerade SQL zu tun, falls gewünscht:

public IEnumerable<string> AdHocChange()
{
  var reader = "select * from SampleTable".ExecuteReader();
  while (reader.Read())
  {
    // Do stuff here like yield return strings
  }
    var name = "select top 1 name from sysobjects"
      .ExecuteScalar() as string;
    yield return "drop table SampleTable";
    yield return "drop table AnotherSampleTable";
  }

Fügen Sie die AdHocChange-Methode, wie eine andere "yield Return"-Methode aufrufen, und Eiche werden diese Befehle auch fröhlich durchführen. (Beachten Sie, dass verlierst du verfolgen, dass Wiki-Link, Eiche es Fehler/Help-Meldung enthält, die es anzeigt.)

Ich kann nicht ohne Ton Ziegel machen!

Übrigens, wenn die Datenbank einige Samen-Daten benötigt, dies ist auch Teil der SeedController Verantwortung, und wieder fällt es in der Schema-Klasse zu tun, diesmal über die SampleEntries-Methode. Da dieses System echte Ausgangswerte hat, die muss hier sein, werde ich dies allein lassen.

Sobald die SeedController kompiliert wird, Sidekick wird erneut das Projekt bereitstellen, aber wie die meisten Controller wird nicht es bis Hit mit einer HTTP-Anforderung aktiviert. Wenn Sie einen der Blick über die SeedController nicht, werfen Sie einen Blick. Vier POST Endpunkte exportiert wird: PurgeDB, Exporte, alle und SampleEntries. Während Sie sicherlich die Endpunkte selbst treffen könnte, dies ist die Art von sich wiederholenden Vorgang, der am besten Links für Automatisierung ist — die im Falle von Eiche Mittel Rechen. Ab Reset sicher genug, "rake" alle Tabellen und regenerieren das Schema (es wird ein Beitrag zur /seed/PurgeDB und dann eine andere Stelle/Saatgut / alle), und "Rechen-Beispiel" fallen alle Tabellen, regenerieren das Schema und die Beispieldaten (Beitrag /seed/SampleEntries) zu generieren. Nur auf Vollständigkeit wird übrigens ein "Rake-Export" (oder eine POST-/seed/export) die SQL-Anweisungen verwendet, um diese Dinge tun zurück.

(Curl oder Ruby können dabei einen Beitrag von der Kommandozeile eine einzeilige Übung übrigens. Die Rakefile.rb-Datei hat Beispiele dafür, wie die POST mit Net::HTTP::post_from zu tun, die ziemlich einfach Ausschneiden und Einfügen in eine andere .rb Datei, wenn Sie nicht, es innerhalb der Rakefile begraben möchten. Oder Sie könnten dies als eine Einstiegsdroge zum Lernen von Ruby verwenden. Niemand richtet.)

Es lebt!

Angenommen, es gibt keine Tippfehler, erledigt Rake zurücksetzen, bringt eine Aktualisierung im Browser eine Webseite arbeiten mit einem einfachen Text-Feld (für die Blog-Titel) und einen "submit"-Button. Einen neuen Blog-Titel eingeben, wird jedoch ein Fehler generiert — obwohl Blogs vorhanden sind, gibt es irgendwie eine Annahme (basierend auf was in der Index.cshtml angezeigt wird), dass es auch irgendwie etwas zugeordnet Blogs aufgerufen Kommentare.

Im einfachen relationalen Modell, das die Blogging-Engine-Welt dominiert, haben Blogs eine eins-zu-viele-Beziehung auf Kommentare. Ich möchte in diesem System, Modell also zuerst ich brauche einen Datentyp für Comment-Objekten, die hirntoten einfach wieder. In der Tat, denn Kommentare (wie Blog-Objekte) im wesentlichen dynamische Objekte ohne interessante Elemente sind, sie brauchen nicht einmal eine Modell-Klassendefinition — das hat All-Dynamik-Objekt (der Gemini-Typ, für diejenigen, die meine Spalte August 2013 "Wird dynamisch mit the Gemini Library," erinnern an msdn.microsoft.com/magazine/dn342877) ist in Ordnung.

(Und ja, wenn Sie eine Art "Wir sind einen langen Weg aus Kansas, Toto" Augenblick schon früher gehabt haben, das ist auf jeden Fall Zeit zu stoppen und darüber nachzudenken: Sie arbeiten mit einem Geschäftsobjekt dessen Typ Sie nicht die Mühe, definieren.)

Um das Verhältnis von Kommentaren in Blogs zu beschreiben, jedoch müssen Sie zwei Dinge tun. Zuerst Kommentare braucht ein Repository (wie Blogs in meinem letzten Artikel):

public class Comments : DynamicRepository
{
}

Noch bedeutsamer ist, die Blog-Klasse muss etwas überarbeitet werden, um die eins-zu-viele-Beziehung, beide direkt erfassen (Blog besitzen eine Auflistung von Comment-Objekten, die in diesem Fall bedeutet, dass ein Kommentare-Objekt als ein Feld), als auch indirekt (also Eiche weiß, dass Blog und Kommentare-Objekte in der Datenbank verbunden sind, und wie). Dies geschieht durch die Einführung einer neuen Methode, Associates, der die Beziehung beschreibt, wie in Abbildung 3.

Abbildung 3 beschreiben die eins-zu-viele-Beziehung zwischen Blogs und Kommentare

public class Blog : DynamicModel
{
  Blogs blogs = new Blogs();
  // Define comments
  Comments comments = new Comments();
  public Blog() { }
  public Blog(object dto) : base(dto) { }
  // Add an Associates method to add the Comments() method
  IEnumerable<dynamic> Associates()
  {
    // And define the association
    // For othere examples of associations check out the Oak wiki
    yield return new HasMany(comments);
  }
}

Wie Sie sehen können, ist es nicht wirklich so weit weg von was ich sagte, du brauchst dazu: Das Modell entspricht das abstrakte Konzept eines Blogs ziemlich eng. Dies ist, wo die Schönheit und Kraft der Verwendung von dynamischer Techniken gesehen werden kann. Diese eine Änderung (die Associates-Methode eine "Yield return" von einem HasMany zu tun) tatsächlich löst drei neue Methoden, die hinzugefügte Blog — Kommentare, CommentIds und NeuerKommentar —, um die Beziehung des Kommentars zu unterstützen Objekte auf Blog-Objekte, alle davon sind reine Gerüste und sonst müssen Sie diese Methoden "Lehrgeld" schreiben wurden Sie mit normalen, nicht-dynamische c#. Natürlich, für all dies mit der Datenbank arbeiten, müssen Sie es sichern mit einer Datenbankbeschreibung der Tabelle Kommentar, was bedeutet, du bist wieder da SeedController (und einem anschließenden Rechen-Reset), als angezeigt, Abbildung 4.

Abbildung 4-Datenbank-Beschreibung der Tabelle Kommentare

public class Schema{
  public IEnumerable<Func<dynamic>> Scripts()
  {
    yield return CreateBlogsTable;
    yield return CreateCommentsTable;
  }
  public string CreateBlogsTable() // Here is the function definition
  {
    return Seed.CreateTable("Blogs",
      Seed.Id(),
      new { Name = "nvarchar(255)" },
      new { Body = "nvarchar(max)" }
    );
  }
  public string CreateCommentsTable() // Here is the function definition
  {
    return Seed.CreateTable("Comments",
      Seed.Id(),
      new { BlogId = "int", ForeignKey = "Blogs(Id)" },
      new { Body = "nvarchar(max)" }
    );
  }
}

Weil ich hier bin, werde ich übrigens ein paar Blog-Einträge, nur zu zeigen, wie Sie die SampleEntries-Methode verwenden, hinzufügen. Es ist viel einfacher als Sie denken vielleicht, wie in Abbildung 5.

Abbildung 5 hinzufügen Blog-Einträge

public void SampleEntries(){
  var blog1 = new // Store the ID
  {
    Name = "Hello, Oak Blog",
    Body = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
  }.InsertInto("Blogs");
  new { Body = "great job!", BlogId = blog1 }.InsertInto("Comments");
  new
  {
    Name = "Here are cat pictures!",
    Body = "Meowem hisum collar sit amet, addipisces lick."
  }.InsertInto("Blogs");
}

Wieder einmal macht die Verwendung von dynamischen Objekten und Erweiterungsmethoden es fast nicht wie c# nicht mehr sehen. (In diesem Fall erstellen Sie kein dynamisches Objekt so weit wie das Erstellen einer Instanz eines anonymen Objekts mit den automatisch generierten Eigenschaften Titel und den Text, und dann mithilfe der Erweiterungsmethode InsertInto die tatsächliche Aufnahme zu tun.) Und übrigens, der einzige Grund, das Objekt in der lokalen Variablen von blog1 zu fangen ist, sodass es als Blog-ID-Wert für den Kommentar auf es verwendet werden kann.

Nur zu. Aktualisieren Sie die Datenbank mit einem Rechen-Beispiel, und dann aktualisieren Sie den Browser.

Weiter: Überprüfung von Benutzereingaben

Dies bedeutet einige interessante Sachen, gebremstes, wenn es schon nicht. Sie haben keine Modelltypen definiert, aber Sie haben ein Modell und Datenbank Speicherplatz dafür. Keine SQL-Skripts (obwohl es fair ist zu behaupten, dass die wiederholte Verwendung von ad-hoc-Methoden in der Schema-Klasse leicht zu SQL-Skripts werden könnten) beteiligt waren, und es ist wichtig, darauf hinzuweisen, dass die gesamten Code tun dies alles ist (noch) versteckt im Quelltext im Ordner "Eiche" gestaffelten Projektes, für den Fall, dass Sie Debuggen oder einfach Lust Surfen müssen.

Es gibt noch ein paar Dinge noch zu tun, z. B. Überprüfen der Benutzereingabe um sicherzustellen, es ist alles gut und richtig vor dem Speichern, aber das ist ein gutes Thema für die nächste Zeit.

Glücklich Codierung!

Ted Neward ist der Geschäftsinhaber von Neward & Associates LLC. Er hat mehr als 100 Artikel geschrieben und Autor und Mitautor von einem Dutzend Bücher, darunter "professionelle f# 2.0" (Wrox, 2010). Er ist ein F#-MVP und spricht auf Konferenzen auf der ganzen Welt. Er berät und Mentoren regelmäßig — erreichen ihn bei ted@tedneward.com Wenn Sie daran interessiert, ihn zusammen mit Ihrem Team, oder lesen Sie seinen Blog unter blogs.tedneward.com.

Unser Dank gilt dem folgenden technischen Experten für die Durchsicht dieses Artikels: Amir Rajan (Eiche Projekt Schöpfer)
Amir Rajan ist aktives Mitglied der Entwicklungsgemeinschaft mit Auftritten auf .net Felsen, Herding Code und Hanselminutes. Er verfügt über Expertise in vielen.NET-basierten Web-Frameworks, REST-Architekturen, Ruby, JavaScript (Front-End- und NodeJS), iOS und f#. Er ist immer bestrebt, die Industrie durch open-Source-Beiträge besser, unabhängige Beratung und Bloggen (amirrajan.net) und kann erreicht werden unter ar@amirrajan.net. "