Sdílet prostřednictvím


Vytvoření vrstvy přístupu k datům

Erik Reitan

Tato série kurzů vás naučí základy vytváření ASP.NET Web Forms aplikace pomocí ASP.NET 4.5 a Microsoft Visual Studio Express 2013 pro web. K dispozici je Visual Studio 2013 projekt se zdrojovým kódem jazyka C#, který bude doprovázet tuto sérii kurzů.

Tento kurz popisuje, jak vytvořit data z databáze, přistupovat k datům a kontrolovat je pomocí ASP.NET Web Forms a Entity Framework Code First. Tento kurz vychází z předchozího kurzu Vytvoření projektu a je součástí série kurzů Wingtip Toy Store. Po dokončení tohoto kurzu vytvoříte skupinu tříd přístupu k datům, které jsou ve složce Modely projektu.

Naučíte se:

  • Jak vytvořit datové modely.
  • Postup inicializace a počátečního nastavení databáze
  • Postup aktualizace a konfigurace aplikace pro podporu databáze

V tomto kurzu jsou představeny tyto funkce:

  • Entity Framework Code First
  • LocalDB
  • Datové poznámky

Vytváření datových modelů

Entity Framework je architektura objektově relačního mapování (ORM). Umožňuje pracovat s relačními daty jako objekty a eliminovat většinu kódu pro přístup k datům, který byste obvykle potřebovali napsat. Pomocí Entity Frameworku můžete vydávat dotazy pomocí LINQ a pak načítat data jako objekty silného typu a manipulovat s nimi. LINQ poskytuje vzory pro dotazování a aktualizaci dat. Pomocí Entity Frameworku se můžete soustředit na vytváření zbytku vaší aplikace a nemusíte se soustředit na základy přístupu k datům. Později v této sérii kurzů vám ukážeme, jak pomocí dat naplnit navigační dotazy a dotazy na produkty.

Entity Framework podporuje vývojové paradigma s názvem Code First. Code First umožňuje definovat datové modely pomocí tříd. Třída je konstruktor, který umožňuje vytvářet vlastní typy seskupením proměnných jiných typů, metod a událostí. Třídy můžete mapovat na existující databázi nebo je použít k vygenerování databáze. V tomto kurzu vytvoříte datové modely zápisem tříd datového modelu. Pak necháte Entity Framework vytvářet databázi za chodu z těchto nových tříd.

Začnete vytvořením tříd entit, které definují datové modely pro aplikaci Web Forms. Pak vytvoříte třídu kontextu, která spravuje třídy entit a poskytuje přístup k datům k databázi. Vytvoříte také třídu inicializátoru, kterou použijete k naplnění databáze.

Entity Framework a odkazy

Ve výchozím nastavení se Entity Framework zahrne při vytváření nové webové aplikace ASP.NET pomocí šablony Web Forms. Entity Framework je možné nainstalovat, odinstalovat a aktualizovat jako balíček NuGet.

Tento balíček NuGet obsahuje následující sestavení modulu runtime v rámci vašeho projektu:

  • EntityFramework.dll – veškerý běžný kód modulu runtime používaný službou Entity Framework
  • EntityFramework.SqlServer.dll – zprostředkovatel Microsoftu SQL Server pro Entity Framework

Třídy entit

Třídy, které vytvoříte pro definování schématu dat, se nazývají třídy entit. Pokud s návrhem databáze začínáte, představte si třídy entit jako definice tabulek databáze. Každá vlastnost ve třídě určuje sloupec v tabulce databáze. Tyto třídy poskytují jednoduché, objektově-relační rozhraní mezi objektově orientovaným kódem a relační tabulkovou strukturou databáze.

V tomto kurzu začnete přidáním jednoduchých tříd entit představujících schémata pro produkty a kategorie. Třída products bude obsahovat definice pro každý produkt. Názvy jednotlivých členů produktové třídy budou ProductID, ProductName, Description, ImagePath, UnitPrice, , , CategoryIDa Category. Třída kategorie bude obsahovat definice pro každou kategorii, do které může produkt patřit, například Auto, Loď nebo Letadlo. Název každého člena třídy kategorie bude CategoryID, CategoryName, Descriptiona Products. Každý produkt bude patřit do jedné z kategorií. Tyto třídy entit budou přidány do existující složky Models projektu.

  1. V Průzkumník řešení klikněte pravým tlačítkem na složku Models (Modely) a pak vyberte Add -New Item (Přidat novou>položku).

    Snímek obrazovky okna Průzkumník řešení se zvýrazněnou složkou Modely a vybranými rozevíracími nabídkami Přidat a Nová položka

    Zobrazí se dialogové okno Přidat novou položku.

  2. V části Visual C# v podokně Nainstalované na levé straně vyberte Kód.

    Snímek obrazovky okna Přidat novou položku s podoknem Nainstalované na levé straně s otevřeným jazykem Visual C# a vybranou možností Kód

  3. V prostředním podokně vyberte Třída a pojmenujte tuto novou třídu Product.cs.

  4. Klikněte na Přidat.
    Nový soubor třídy se zobrazí v editoru.

  5. Nahraďte výchozí kód následujícím kódem:

    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. Opakováním kroků 1 až 4 vytvořte jinou třídu, ale novou třídu pojmenujte Category.cs a nahraďte výchozí kód následujícím kódem:

    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; }
        }
    }
    

Jak už jsme zmínili, třída představuje typ produktu, Category který je aplikace určená k prodeji (například "Auta", "Lodě", "Rakety" a tak dále), a Product třída představuje jednotlivé výrobky (hračky) v databázi. Každá instance objektu Product bude odpovídat řádku v tabulce relační databáze a každá vlastnost třídy Product se mapuje na sloupec v tabulce relační databáze. Později v tomto kurzu si projdete produktová data obsažená v databázi.

Datové poznámky

Možná jste si všimli, že někteří členové tříd mají atributy určující podrobnosti o členu, například [ScaffoldColumn(false)]. Jedná se o datové poznámky. Atributy datových poznámek můžou popisovat, jak ověřit vstup uživatele pro daného člena, jak určit jeho formátování a jak se modeluje při vytváření databáze.

Context – třída

Pokud chcete začít používat třídy pro přístup k datům, musíte definovat třídu kontextu. Jak je uvedeno výše, třída kontextu spravuje třídy entit (jako Product je třída a Category třída) a poskytuje přístup k datům k databázi.

Tento postup přidá novou třídu kontextu jazyka C# do složky Models .

  1. Klikněte pravým tlačítkem na složku Models (Modely) a pak vyberte Add -New Item (Přidat novou>položku).
    Zobrazí se dialogové okno Přidat novou položku.

  2. V prostředním podokně vyberte Třída , pojmenujte ji ProductContext.cs a klikněte na Přidat.

  3. Nahraďte výchozí kód obsažený ve třídě následujícím kódem:

    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; }
        }
    }
    

Tento kód přidá System.Data.Entity obor názvů, abyste měli přístup ke všem základním funkcím Entity Frameworku, mezi které patří možnost dotazovat se, vkládat, aktualizovat a odstraňovat data pomocí práce s objekty silného typu.

Třída ProductContext představuje kontext databáze produktu Entity Framework, který zpracovává načítání, ukládání a aktualizaci Product instancí tříd v databázi. Třída ProductContext je odvozena ze DbContext základní třídy poskytované Entity Framework.

Initializer – třída

K inicializaci databáze při prvním použití kontextu budete muset spustit nějakou vlastní logiku. To umožní přidání počátečních dat do databáze, abyste mohli okamžitě zobrazit produkty a kategorie.

Tento postup přidá novou třídu inicializátoru jazyka C# do složky Models .

  1. Ve složce Models vytvořte další Class a pojmenujte ho ProductDatabaseInitializer.cs.

  2. Nahraďte výchozí kód obsažený ve třídě následujícím kódem:

    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;
        }
      }
    }
    

Jak je vidět z výše uvedeného kódu, při vytvoření a inicializaci Seed databáze se vlastnost přepíše a nastaví. Při nastavení Seed vlastnosti se k naplnění databáze použijí hodnoty z kategorií a produktů. Pokud se pokusíte aktualizovat počáteční data úpravou výše uvedeného kódu po vytvoření databáze, neuvidíte při spuštění webové aplikace žádné aktualizace. Důvodem je, že výše uvedený kód používá implementaci DropCreateDatabaseIfModelChanges třídy k rozpoznání, jestli se model (schéma) změnil před resetováním počátečních dat. Pokud nedojde k žádným změnám Category tříd entit a Product , databáze nebude znovu inicializována s počátečními daty.

Poznámka

Pokud chcete, aby se databáze znovu vytvořila při každém spuštění aplikace, mohli byste místo DropCreateDatabaseIfModelChanges třídy použít DropCreateDatabaseAlways třídu. Pro tuto řadu kurzů však použijte DropCreateDatabaseIfModelChanges třídu .

V tomto okamžiku v tomto kurzu budete mít složku Models se čtyřmi novými třídami a jednou výchozí třídou:

Vytvoření složky Data Access Layer - Models

Konfigurace aplikace pro použití datového modelu

Teď, když jste vytvořili třídy, které představují data, musíte nakonfigurovat aplikaci tak, aby používala třídy. V souboru Global.asax přidáte kód, který inicializuje model. V souboruWeb.config přidáte informace, které aplikaci sdělí, jakou databázi použijete k ukládání dat reprezentovaných novými datovými třídami. Soubor Global.asax lze použít ke zpracování událostí nebo metod aplikace. SouborWeb.config umožňuje řídit konfiguraci webové aplikace ASP.NET.

Aktualizace souboru Global.asax

Chcete-li inicializovat datové modely při spuštění aplikace, aktualizujete obslužnou rutinu Application_Start v souboru Global.asax.cs .

Poznámka

V Průzkumník řešení můžete vybrat soubor Global.asax nebo Soubor Global.asax.cs a upravit tak soubor Global.asax.cs.

  1. Do metody v souboru Global.asax.cs přidejte žlutě Application_Start zvýrazněný následující kód.

    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());
            }
        }
    }
    

Poznámka

Pokud chcete při prohlížení této série kurzů v prohlížeči zobrazit kód zvýrazněný žlutě, musí váš prohlížeč podporovat HTML5.

Jak je znázorněno ve výše uvedeném kódu, aplikace při spuštění aplikace určuje inicializátor, který se spustí při prvním přístupu k datům. Pro přístup k objektu a objektu DatabaseProductDatabaseInitializer jsou vyžadovány dva další obory názvů.

Úprava souboru Web.Config

Přestože Entity Framework Code First vygeneruje databázi ve výchozím umístění, když je databáze naplněna počátečními daty, přidáním vlastních informací o připojení k aplikaci získáte kontrolu nad umístěním databáze. Toto připojení k databázi zadáte pomocí připojovacího řetězce v souboruWeb.config aplikace v kořenovém adresáři projektu. Přidáním nového připojovacího řetězce můžete místo výchozího umístění nasměrovat umístění databáze (wingtiptoys.mdf) do adresáře dat aplikace (App_Data). Provedení této změny vám umožní najít a zkontrolovat soubor databáze později v tomto kurzu.

  1. V Průzkumník řešení vyhledejte a otevřete soubor Web.config.

  2. Následujícím způsobem přidejte do oddílu <connectionStrings> souboruWeb.config připojovací řetězec zvýrazněný žlutě:

    <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>
    

Při prvním spuštění aplikace se sestaví databáze v umístění určeném připojovacím řetězcem. Ale před spuštěním aplikace ji nejprve sestavte.

Sestavení aplikace

Chcete-li zajistit, aby všechny třídy a změny webové aplikace fungovaly, měli byste aplikaci sestavit.

  1. V nabídce Debug (Ladění ) vyberte Build WingtipToys (Sestavit WingtipToys).
    Zobrazí se okno Výstup , a pokud vše proběhlo správně, zobrazí se zpráva o úspěšném dokončení .

    Vytvoření vrstvy přístupu k datům – Výstupní okna

Pokud narazíte na chybu, znovu zkontrolujte výše uvedené kroky. Informace v okně Výstup budou indikovat, u kterého souboru došlo k problému a kde se v souboru vyžaduje změna. Tyto informace vám umožní určit, jakou část výše uvedených kroků je potřeba v projektu zkontrolovat a opravit.

Souhrn

V tomto kurzu řady jste vytvořili datový model a také přidali kód, který se použije k inicializaci a nasazení databáze. Také jste aplikaci nakonfigurovali tak, aby při spuštění aplikace používala datové modely.

V dalším kurzu aktualizujete uživatelské rozhraní, přidáte navigaci a načtete data z databáze. Výsledkem bude automatické vytvoření databáze na základě tříd entit, které jste vytvořili v tomto kurzu.

Další materiály

Přehled Entity Framework
Příručka pro začátečníky k ADO.NET Entity Frameworku
Code First Development with Entity FrameworkCode First Relationships Fluent API
Datové poznámky code first
Vylepšení produktivity pro Entity Framework