Freigeben über


Erstellen der Datenzugriffsschicht

von Erik Reitan

In dieser Tutorialreihe erfahren Sie die Grundlagen zum Erstellen einer ASP.NET Web Forms-Anwendung mit ASP.NET 4.5 und Microsoft Visual Studio Express 2013 für Web. Für diese Tutorialreihe steht ein Visual Studio 2013 Projekt mit C#-Quellcode zur Verfügung.

In diesem Tutorial wird beschrieben, wie Sie Mithilfe von ASP.NET Web Forms und Entity Framework Code First Daten aus einer Datenbank erstellen, darauf zugreifen und diese überprüfen. Dieses Tutorial baut auf dem vorherigen Tutorial "Erstellen des Projekts" auf und ist Teil der Tutorialreihe Wingtip Toy Store. Nach Abschluss dieses Tutorials haben Sie eine Gruppe von Datenzugriffsklassen erstellt, die sich im Ordner Models des Projekts befinden.

Sie lernen Folgendes:

  • Erstellen der Datenmodelle
  • Initialisieren und Seeden der Datenbank.
  • Aktualisieren und Konfigurieren der Anwendung zur Unterstützung der Datenbank

Die folgenden Features werden im Tutorial vorgestellt:

  • Entity Framework Code First
  • LocalDB
  • Datenanmerkungen

Erstellen der Datenmodelle

Entity Framework ist ein objektrelationales Zuordnungsframework (ORM). Damit können Sie mit relationalen Daten als Objekte arbeiten, sodass der Großteil des Datenzugriffscodes, den Sie normalerweise schreiben müssen, wegfällt. Mit Entity Framework können Sie Abfragen mithilfe von LINQ ausstellen und dann Daten als stark typisierte Objekte abrufen und bearbeiten. LINQ bietet Muster zum Abfragen und Aktualisieren von Daten. Mithilfe von Entity Framework können Sie sich auf das Erstellen des rests Ihrer Anwendung konzentrieren, anstatt sich auf die Grundlagen des Datenzugriffs zu konzentrieren. Weiter unten in dieser Tutorialreihe erfahren Sie, wie Sie die Daten verwenden, um Navigations- und Produktabfragen aufzufüllen.

Entity Framework unterstützt ein Entwicklungsparadigma namens Code First. Mit Code First können Sie Ihre Datenmodelle mithilfe von Klassen definieren. Eine Klasse ist ein Konstrukt, das Ihnen ermöglicht, Ihre eigenen benutzerdefinierten Typen zu erstellen, indem Variablen anderer Typen, Methoden und Ereignisse zusammengefasst werden. Sie können Klassen einer vorhandenen Datenbank zuordnen oder zum Generieren einer Datenbank verwenden. In diesem Tutorial erstellen Sie die Datenmodelle, indem Sie Datenmodellklassen schreiben. Anschließend lassen Sie Entity Framework die Datenbank aus diesen neuen Klassen erstellen.

Zunächst erstellen Sie die Entitätsklassen, die die Datenmodelle für die Web Forms Anwendung definieren. Anschließend erstellen Sie eine Kontextklasse, die die Entitätsklassen verwaltet und Datenzugriff auf die Datenbank ermöglicht. Außerdem erstellen Sie eine Initialisiererklasse, die Sie zum Auffüllen der Datenbank verwenden.

Entity Framework und Verweise

Entity Framework ist standardmäßig enthalten, wenn Sie mithilfe der Web Forms-Vorlage eine neue ASP.NET-Webanwendung erstellen. Entity Framework kann als NuGet-Paket installiert, deinstalliert und aktualisiert werden.

Dieses NuGet-Paket enthält die folgenden Laufzeitassemblys in Ihrem Projekt:

  • EntityFramework.dll : Der gesamte common runtime-Code, der von Entity Framework verwendet wird
  • EntityFramework.SqlServer.dll – Der Microsoft SQL Server-Anbieter für Entity Framework

Entitätsklassen

Die Klassen, die Sie zum Definieren des Schemas der Daten erstellen, werden als Entitätsklassen bezeichnet. Wenn Sie noch nicht mit dem Datenbankentwurf vertraut sind, stellen Sie sich die Entitätsklassen als Tabellendefinitionen einer Datenbank vor. Jede Eigenschaft in der -Klasse gibt eine Spalte in der Tabelle der Datenbank an. Diese Klassen bieten eine einfache, objektrelationale Schnittstelle zwischen objektorientiertem Code und der relationalen Tabellenstruktur der Datenbank.

In diesem Tutorial beginnen Sie mit dem Hinzufügen einfacher Entitätsklassen, die die Schemas für Produkte und Kategorien darstellen. Die Produktklasse enthält Definitionen für jedes Produkt. Der Name jedes Members der Produktklasse lautet ProductID, , ProductName, Description, ImagePath, UnitPrice, CategoryIDund Category. Die Kategorieklasse enthält Definitionen für jede Kategorie, zu der ein Produkt gehören kann, z. B. Auto, Boot oder Flugzeug. Der Name der einzelnen Member der Kategorieklasse lautet CategoryID, , CategoryNameDescriptionund Products. Jedes Produkt gehört zu einer der Kategorien. Diese Entitätsklassen werden dem vorhandenen Ordner Models des Projekts hinzugefügt.

  1. Klicken Sie in Projektmappen-Explorer mit der rechten Maustaste auf den Ordner Models, und wählen Sie dann Hinzufügen –>Neues Element aus.

    Screenshot des Projektmappen-Explorer Fensters mit hervorgehobenem Ordner

    Das Dialogfeld Neues Element hinzufügen wird angezeigt.

  2. Wählen Sie unter Visual C# im Bereich Installiert auf der linken Seite die Option Code aus.

    Screenshot des Fensters

  3. Wählen Sie im mittleren Bereich Klasse aus, und nennen Sie diese neue Klasse Product.cs.

  4. Klicken Sie auf Hinzufügen.
    Die neue Klassendatei wird im Editor angezeigt.

  5. Ersetzen Sie den Standardcode durch den folgenden Code:

    using System.ComponentModel.DataAnnotations;
    
    namespace WingtipToys.Models
    {
        public class Product
        {
            [ScaffoldColumn(false)]
            public int ProductID { get; set; }
    
            [Required, StringLength(100), Display(Name = "Name")]
            public string ProductName { get; set; }
    
            [Required, StringLength(10000), Display(Name = "Product Description"), DataType(DataType.MultilineText)]
            public string Description { get; set; }
    
            public string ImagePath { get; set; }
    
            [Display(Name = "Price")]
            public double? UnitPrice { get; set; }
    
            public int? CategoryID { get; set; }
    
            public virtual Category Category { get; set; }
        }
    }
    
  6. Erstellen Sie eine weitere Klasse, indem Sie die Schritte 1 bis 4 wiederholen. Nennen Sie jedoch die neue Klasse Category.cs , und ersetzen Sie den Standardcode durch den folgenden Code:

    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    
    namespace WingtipToys.Models
    {
        public class Category
        {
            [ScaffoldColumn(false)]
            public int CategoryID { get; set; }
    
            [Required, StringLength(100), Display(Name = "Name")]
            public string CategoryName { get; set; }
    
            [Display(Name = "Product Description")]
            public string Description { get; set; }
    
            public virtual ICollection<Product> Products { get; set; }
        }
    }
    

Wie bereits erwähnt, stellt die Category Klasse den Produkttyp dar, den die Anwendung verkaufen soll (z . B. "Cars", "Boats", "Rockets" usw.), und die Product Klasse stellt die einzelnen Produkte (Spielzeuge) in der Datenbank dar. Jede instance eines Product Objekts entspricht einer Zeile in einer relationalen Datenbanktabelle, und jede Eigenschaft der Product-Klasse wird einer Spalte in der relationalen Datenbanktabelle zugeordnet. Weiter unten in diesem Tutorial überprüfen Sie die Produktdaten, die in der Datenbank enthalten sind.

Datenanmerkungen

Möglicherweise haben Sie bemerkt, dass bestimmte Member der Klassen Attribute enthalten, die Details zum Member angeben, z [ScaffoldColumn(false)]. B. . Dies sind Datenanmerkungen. Die Datenanmerkungsattribute können beschreiben, wie Benutzereingaben für dieses Element überprüft werden, um formatierungen dafür anzugeben und anzugeben, wie sie beim Erstellen der Datenbank modelliert wird.

Context-Klasse

Um die Klassen für den Datenzugriff zu verwenden, müssen Sie eine Kontextklasse definieren. Wie bereits erwähnt, verwaltet die Kontextklasse die Entitätsklassen (z. B. die Product -Klasse und die Category -Klasse) und bietet Datenzugriff auf die Datenbank.

Mit diesem Verfahren wird dem Ordner Models eine neue C#-Kontextklasse hinzugefügt.

  1. Klicken Sie mit der rechten Maustaste auf den Ordner Models , und wählen Sie dann Hinzufügen –>Neues Element aus.
    Das Dialogfeld Neues Element hinzufügen wird angezeigt.

  2. Wählen Sie im mittleren Bereich Klasse aus, nennen Sie ihn ProductContext.cs , und klicken Sie auf Hinzufügen.

  3. Ersetzen Sie den in der -Klasse enthaltenen Standardcode durch den folgenden Code:

    using System.Data.Entity;
    namespace WingtipToys.Models
    {
        public class ProductContext : DbContext
        {
            public ProductContext() : base("WingtipToys")
            {
            }
            public DbSet<Category> Categories { get; set; }
            public DbSet<Product> Products { get; set; }
        }
    }
    

Dieser Code fügt den System.Data.Entity Namespace hinzu, sodass Sie Zugriff auf alle Kernfunktionen von Entity Framework haben, einschließlich der Funktion zum Abfragen, Einfügen, Aktualisieren und Löschen von Daten durch Arbeiten mit stark typisierten Objekten.

Die ProductContext -Klasse stellt den Entity Framework-Produktdatenbankkontext dar, der das Abrufen, Speichern und Aktualisieren von Product Klasseninstanzen in der Datenbank verarbeitet. Die ProductContext -Klasse leitet sich von der Basisklasse ab, die DbContext von Entity Framework bereitgestellt wird.

Initialisiererklasse

Sie müssen eine benutzerdefinierte Logik ausführen, um die Datenbank bei der ersten Verwendung des Kontexts zu initialisieren. Dadurch können Seeddaten zur Datenbank hinzugefügt werden, sodass Sie Produkte und Kategorien sofort anzeigen können.

Mit diesem Verfahren wird dem Ordner Models eine neue C#-Initialisiererklasse hinzugefügt.

  1. Erstellen Sie einen weiteren Class im Ordner Models , und nennen Sie sie ProductDatabaseInitializer.cs.

  2. Ersetzen Sie den in der -Klasse enthaltenen Standardcode durch den folgenden Code:

    using System.Collections.Generic;
    using System.Data.Entity;
    
    namespace WingtipToys.Models
    {
      public class ProductDatabaseInitializer : DropCreateDatabaseIfModelChanges<ProductContext>
      {
        protected override void Seed(ProductContext context)
        {
          GetCategories().ForEach(c => context.Categories.Add(c));
          GetProducts().ForEach(p => context.Products.Add(p));
        }
    
        private static List<Category> GetCategories()
        {
          var categories = new List<Category> {
                    new Category
                    {
                        CategoryID = 1,
                        CategoryName = "Cars"
                    },
                    new Category
                    {
                        CategoryID = 2,
                        CategoryName = "Planes"
                    },
                    new Category
                    {
                        CategoryID = 3,
                        CategoryName = "Trucks"
                    },
                    new Category
                    {
                        CategoryID = 4,
                        CategoryName = "Boats"
                    },
                    new Category
                    {
                        CategoryID = 5,
                        CategoryName = "Rockets"
                    },
                };
    
          return categories;
        }
    
        private static List<Product> GetProducts()
        {
          var products = new List<Product> {
                    new Product
                    {
                        ProductID = 1,
                        ProductName = "Convertible Car",
                        Description = "This convertible car is fast! The engine is powered by a neutrino based battery (not included)." + 
                                      "Power it up and let it go!", 
                        ImagePath="carconvert.png",
                        UnitPrice = 22.50,
                        CategoryID = 1
                   },
                    new Product 
                    {
                        ProductID = 2,
                        ProductName = "Old-time Car",
                        Description = "There's nothing old about this toy car, except it's looks. Compatible with other old toy cars.",
                        ImagePath="carearly.png",
                        UnitPrice = 15.95,
                         CategoryID = 1
                   },
                    new Product
                    {
                        ProductID = 3,
                        ProductName = "Fast Car",
                        Description = "Yes this car is fast, but it also floats in water.",
                        ImagePath="carfast.png",
                        UnitPrice = 32.99,
                        CategoryID = 1
                    },
                    new Product
                    {
                        ProductID = 4,
                        ProductName = "Super Fast Car",
                        Description = "Use this super fast car to entertain guests. Lights and doors work!",
                        ImagePath="carfaster.png",
                        UnitPrice = 8.95,
                        CategoryID = 1
                    },
                    new Product
                    {
                        ProductID = 5,
                        ProductName = "Old Style Racer",
                        Description = "This old style racer can fly (with user assistance). Gravity controls flight duration." + 
                                      "No batteries required.",
                        ImagePath="carracer.png",
                        UnitPrice = 34.95,
                        CategoryID = 1
                    },
                    new Product
                    {
                        ProductID = 6,
                        ProductName = "Ace Plane",
                        Description = "Authentic airplane toy. Features realistic color and details.",
                        ImagePath="planeace.png",
                        UnitPrice = 95.00,
                        CategoryID = 2
                    },
                    new Product
                    {
                        ProductID = 7,
                        ProductName = "Glider",
                        Description = "This fun glider is made from real balsa wood. Some assembly required.",
                        ImagePath="planeglider.png",
                        UnitPrice = 4.95,
                        CategoryID = 2
                    },
                    new Product
                    {
                        ProductID = 8,
                        ProductName = "Paper Plane",
                        Description = "This paper plane is like no other paper plane. Some folding required.",
                        ImagePath="planepaper.png",
                        UnitPrice = 2.95,
                        CategoryID = 2
                    },
                    new Product
                    {
                        ProductID = 9,
                        ProductName = "Propeller Plane",
                        Description = "Rubber band powered plane features two wheels.",
                        ImagePath="planeprop.png",
                        UnitPrice = 32.95,
                        CategoryID = 2
                    },
                    new Product
                    {
                        ProductID = 10,
                        ProductName = "Early Truck",
                        Description = "This toy truck has a real gas powered engine. Requires regular tune ups.",
                        ImagePath="truckearly.png",
                        UnitPrice = 15.00,
                        CategoryID = 3
                    },
                    new Product
                    {
                        ProductID = 11,
                        ProductName = "Fire Truck",
                        Description = "You will have endless fun with this one quarter sized fire truck.",
                        ImagePath="truckfire.png",
                        UnitPrice = 26.00,
                        CategoryID = 3
                    },
                    new Product
                    {
                        ProductID = 12,
                        ProductName = "Big Truck",
                        Description = "This fun toy truck can be used to tow other trucks that are not as big.",
                        ImagePath="truckbig.png",
                        UnitPrice = 29.00,
                        CategoryID = 3
                    },
                    new Product
                    {
                        ProductID = 13,
                        ProductName = "Big Ship",
                        Description = "Is it a boat or a ship. Let this floating vehicle decide by using its " + 
                                      "artifically intelligent computer brain!",
                        ImagePath="boatbig.png",
                        UnitPrice = 95.00,
                        CategoryID = 4
                    },
                    new Product
                    {
                        ProductID = 14,
                        ProductName = "Paper Boat",
                        Description = "Floating fun for all! This toy boat can be assembled in seconds. Floats for minutes!" + 
                                      "Some folding required.",
                        ImagePath="boatpaper.png",
                        UnitPrice = 4.95,
                        CategoryID = 4
                    },
                    new Product
                    {
                        ProductID = 15,
                        ProductName = "Sail Boat",
                        Description = "Put this fun toy sail boat in the water and let it go!",
                        ImagePath="boatsail.png",
                        UnitPrice = 42.95,
                        CategoryID = 4
                    },
                    new Product
                    {
                        ProductID = 16,
                        ProductName = "Rocket",
                        Description = "This fun rocket will travel up to a height of 200 feet.",
                        ImagePath="rocket.png",
                        UnitPrice = 122.95,
                        CategoryID = 5
                    }
                };
    
          return products;
        }
      }
    }
    

Wie Sie im obigen Code sehen können, wird die Eigenschaft überschrieben und festgelegt, wenn die Seed Datenbank erstellt und initialisiert wird. Wenn die Seed -Eigenschaft festgelegt ist, werden die Werte aus den Kategorien und Produkten verwendet, um die Datenbank aufzufüllen. Wenn Sie versuchen, die Seeddaten zu aktualisieren, indem Sie den obigen Code ändern, nachdem die Datenbank erstellt wurde, werden beim Ausführen der Webanwendung keine Updates angezeigt. Der Grund dafür ist, dass der obige Code eine Implementierung der DropCreateDatabaseIfModelChanges -Klasse verwendet, um zu erkennen, ob sich das Modell (Schema) vor dem Zurücksetzen der Seeddaten geändert hat. Wenn keine Änderungen an den Entitätsklassen Category und Product vorgenommen werden, wird die Datenbank nicht mit den Seeddaten neu initialisiert.

Hinweis

Wenn Sie möchten, dass die Datenbank jedes Mal neu erstellt wird, wenn Sie die Anwendung ausgeführt haben, können Sie die DropCreateDatabaseAlways -Klasse anstelle der DropCreateDatabaseIfModelChanges -Klasse verwenden. Verwenden Sie für diese Tutorialreihe jedoch die DropCreateDatabaseIfModelChanges -Klasse.

An diesem Punkt in diesem Tutorial verfügen Sie über einen Ordner Models mit vier neuen Klassen und einer Standardklasse:

Erstellen der Datenzugriffsebene – Ordner

Konfigurieren der Anwendung für die Verwendung des Datenmodells

Nachdem Sie nun die Klassen erstellt haben, die die Daten darstellen, müssen Sie die Anwendung so konfigurieren, dass sie die Klassen verwendet. In der Datei Global.asax fügen Sie Code hinzu, der das Modell initialisiert. In der Web.config-Datei fügen Sie Informationen hinzu, die der Anwendung angibt, welche Datenbank Sie zum Speichern der Daten verwenden, die durch die neuen Datenklassen dargestellt werden. Die Datei Global.asax kann zum Behandeln von Anwendungsereignissen oder -methoden verwendet werden. Mit derWeb.config-Datei können Sie die Konfiguration Ihrer ASP.NET-Webanwendung steuern.

Aktualisieren der Datei "Global.asax"

Um die Datenmodelle beim Start der Anwendung zu initialisieren, aktualisieren Sie den Application_Start Handler in der Datei Global.asax.cs .

Hinweis

In Projektmappen-Explorer können Sie entweder die Datei Global.asax oder global.asax.cs auswählen, um die Datei Global.asax.cs zu bearbeiten.

  1. Fügen Sie der Methode in der Datei Global.asax.cs den Application_Start folgenden gelb hervorgehobenen Code hinzu.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Optimization;
    using System.Web.Routing;
    using System.Web.Security;
    using System.Web.SessionState;
    using System.Data.Entity;
    using WingtipToys.Models;
    
    namespace WingtipToys
    {
        public class Global : HttpApplication
        {
            void Application_Start(object sender, EventArgs e)
            {
                // Code that runs on application startup
                RouteConfig.RegisterRoutes(RouteTable.Routes);
                BundleConfig.RegisterBundles(BundleTable.Bundles);
    
                // Initialize the product database.
                Database.SetInitializer(new ProductDatabaseInitializer());
            }
        }
    }
    

Hinweis

Ihr Browser muss HTML5 unterstützen, um den gelb hervorgehobenen Code beim Anzeigen dieser Tutorialreihe in einem Browser anzuzeigen.

Wie im obigen Code gezeigt, gibt die Anwendung beim Start der Anwendung den Initialisierer an, der beim ersten Zugriff auf die Daten ausgeführt wird. Die beiden zusätzlichen Namespaces sind für den Zugriff auf das Database -Objekt und das ProductDatabaseInitializer -Objekt erforderlich.

Ändern der Web.Config-Datei

Obwohl Entity Framework Code First eine Datenbank an einem Standardspeicherort generiert, wenn die Datenbank mit Startdaten aufgefüllt wird, erhalten Sie durch das Hinzufügen eigener Verbindungsinformationen zu Ihrer Anwendung die Kontrolle über den Datenbankspeicherort. Sie geben diese Datenbankverbindung mithilfe einer Verbindungszeichenfolge in der Web.config Datei der Anwendung im Stammverzeichnis des Projekts an. Durch Hinzufügen einer neuen Verbindungszeichenfolge können Sie den Speicherort der Datenbank (wingtiptoys.mdf) anweisen, die im Datenverzeichnis der Anwendung (App_Data) erstellt werden soll, anstatt den Standardspeicherort. Wenn Sie diese Änderung vornehmen, können Sie die Datenbankdatei später in diesem Tutorial suchen und überprüfen.

  1. Suchen und öffnen Sie in Projektmappen-Explorer die dateiWeb.config.

  2. Fügen Sie die gelb hervorgehobene Verbindungszeichenfolge dem <connectionStrings> Abschnitt der Web.config-Datei wie folgt hinzu:

    <connectionStrings>
    <add name="DefaultConnection" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\aspnet-WingtipToys-20131119102907.mdf;Initial Catalog=aspnet-WingtipToys-20131119102907;Integrated Security=True"
    providerName="System.Data.SqlClient" />
    <add name="WingtipToys"
    connectionString="Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\wingtiptoys.mdf;Integrated Security=True"
    providerName="System.Data.SqlClient" />
    </connectionStrings>
    

Wenn die Anwendung zum ersten Mal ausgeführt wird, wird die Datenbank an dem durch die Verbindungszeichenfolge angegebenen Speicherort erstellt. Vor dem Ausführen der Anwendung erstellen wir sie jedoch zuerst.

Erstellen der Anwendung

Um sicherzustellen, dass alle Klassen und Änderungen an Ihrer Webanwendung funktionieren, sollten Sie die Anwendung erstellen.

  1. Wählen Sie im Menü Debuggen die Option WingtipToys erstellen aus.
    Das Fenster Ausgabe wird angezeigt, und wenn alles gut gelaufen ist, wird eine Meldung erfolgreich angezeigt.

    Erstellen der Datenzugriffsebene – Ausgabefenster

Wenn ein Fehler auftritt, überprüfen Sie die oben genannten Schritte erneut. Die Informationen im Ausgabefenster geben an, welche Datei ein Problem hat und wo in der Datei eine Änderung erforderlich ist. Anhand dieser Informationen können Sie bestimmen, welcher Teil der oben genannten Schritte in Ihrem Projekt überprüft und festgelegt werden muss.

Zusammenfassung

In diesem Tutorial der Reihe haben Sie das Datenmodell erstellt und den Code hinzugefügt, der zum Initialisieren und Seeding der Datenbank verwendet wird. Außerdem haben Sie die Anwendung so konfiguriert, dass die Datenmodelle verwendet werden, wenn die Anwendung ausgeführt wird.

Im nächsten Tutorial aktualisieren Sie die Benutzeroberfläche, fügen Navigation hinzu und rufen Daten aus der Datenbank ab. Dies führt dazu, dass die Datenbank automatisch basierend auf den Entitätsklassen erstellt wird, die Sie in diesem Tutorial erstellt haben.

Zusätzliche Ressourcen

Übersicht über Entity Framework
Leitfaden für Einsteiger in das ADO.NET Entity Framework
Code First-Entwicklung mit Entity FrameworkCode First Relationships Fluent-API
Code First Data Annotations
Produktivitätsverbesserungen für Entity Framework