Tworzenie warstwy dostępu do danych
Ta seria samouczków zawiera podstawowe informacje dotyczące tworzenia aplikacji ASP.NET Web Forms przy użyciu ASP.NET 4.5 i Microsoft Visual Studio Express 2013 for Web. Dostępny jest projekt Visual Studio 2013 z kodem źródłowym języka C#, który towarzyszy tej serii samouczków.
W tym samouczku opisano sposób tworzenia, uzyskiwania dostępu i przeglądania danych z bazy danych przy użyciu ASP.NET Web Forms i Entity Framework Code First. Ten samouczek jest oparty na poprzednim samouczku "Tworzenie projektu" i jest częścią serii samouczków Wingtip Toy Store. Po ukończeniu tego samouczka utworzysz grupę klas dostępu do danych, które znajdują się w folderze Models projektu.
Zawartość:
- Jak tworzyć modele danych.
- Jak zainicjować i zainicjować bazę danych.
- Jak zaktualizować i skonfigurować aplikację do obsługi bazy danych.
Są to funkcje wprowadzone w samouczku:
- Entity Framework Code First
- LocalDB
- Adnotacje danych
Tworzenie modeli danych
Entity Framework to struktura mapowania obiektowo-relacyjnego (ORM). Umożliwia ona pracę z danymi relacyjnymi jako obiektami, eliminując większość kodu dostępu do danych, który zwykle trzeba będzie napisać. Korzystając z platformy Entity Framework, można wysyłać zapytania przy użyciu LINQ, a następnie pobierać dane i manipulować nimi jako silnie typizowane obiekty. LINQ udostępnia wzorce do wykonywania zapytań i aktualizowania danych. Korzystanie z programu Entity Framework umożliwia skoncentrowanie się na tworzeniu pozostałej części aplikacji, a nie skupieniu się na podstawach dostępu do danych. W dalszej części tej serii samouczków pokażemy, jak używać danych do wypełniania zapytań dotyczących nawigacji i produktów.
Platforma Entity Framework obsługuje paradygmat programowania o nazwie Code First. Funkcja Code First umożliwia definiowanie modeli danych przy użyciu klas. Klasa to konstrukcja, która umożliwia tworzenie własnych typów niestandardowych przez grupowanie zmiennych innych typów, metod i zdarzeń. Klasy można mapować na istniejącą bazę danych lub użyć ich do wygenerowania bazy danych. W tym samouczku utworzysz modele danych, zapisując klasy modelu danych. Następnie pozwolisz programowi Entity Framework utworzyć bazę danych na bieżąco z tych nowych klas.
Zaczniesz od utworzenia klas jednostek, które definiują modele danych dla aplikacji Web Forms. Następnie utworzysz klasę kontekstu, która zarządza klasami jednostek i zapewnia dostęp do danych do bazy danych. Utworzysz również klasę inicjatora, która będzie używana do wypełniania bazy danych.
Entity Framework i odwołania
Domyślnie program Entity Framework jest dołączany podczas tworzenia nowej aplikacji internetowej ASP.NET przy użyciu szablonu Web Forms. Program Entity Framework można zainstalować, odinstalować i zaktualizować jako pakiet NuGet.
Ten pakiet NuGet zawiera następujące zestawy środowiska uruchomieniowego w projekcie:
- EntityFramework.dll — cały wspólny kod środowiska uruchomieniowego używany przez platformę Entity Framework
- EntityFramework.SqlServer.dll — dostawca SQL Server firmy Microsoft dla programu Entity Framework
Klasy jednostek
Klasy tworzone w celu zdefiniowania schematu danych są nazywane klasami jednostek. Jeśli jesteś nowym użytkownikiem projektu bazy danych, pomyśl o klasach jednostek jako definicjach tabel bazy danych. Każda właściwość w klasie określa kolumnę w tabeli bazy danych. Te klasy zapewniają lekki, obiektowo-relacyjny interfejs między kodem obiektowym a strukturą tabeli relacyjnej bazy danych.
W tym samouczku zaczniesz od dodania prostych klas jednostek reprezentujących schematy produktów i kategorii. Klasa products będzie zawierać definicje dla każdego produktu. Nazwa każdej z składowych klasy produktu to ProductID
, ProductName
, Description
, ImagePath
, UnitPrice
, CategoryID
, i Category
. Klasa kategorii będzie zawierać definicje dla każdej kategorii, do których może należeć produkt, na przykład Samochód, Łódź lub Płaszczyzna. Nazwa każdej z składowych klasy kategorii to CategoryID
, CategoryName
, Description
i Products
. Każdy produkt będzie należeć do jednej z kategorii. Te klasy jednostek zostaną dodane do istniejącego folderu Models projektu.
W Eksplorator rozwiązań kliknij prawym przyciskiem myszy folder Models, a następnie wybierz polecenie Dodaj ->Nowy element.
Zostanie wyświetlone okno dialogowe Dodaj nowy element.
W obszarze Visual C# w okienku Zainstalowane po lewej stronie wybierz pozycję Kod.
Wybierz pozycję Klasa w środkowym okienku i nadaj tej nowej klasie nazwę Product.cs.
Kliknij pozycję Dodaj.
Nowy plik klasy jest wyświetlany w edytorze.Zastąp kod domyślny następującym kodem:
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; } } }
Utwórz kolejną klasę, powtarzając kroki od 1 do 4, jednak nadaj nowej klasie nazwę Category.cs i zastąp kod domyślny następującym kodem:
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 wspomniano wcześniej, klasa reprezentuje typ produktu, Category
który aplikacja jest przeznaczona do sprzedaży (na przykład "Samochody", "Łodzie", "Rakiety" itd.), a Product
klasa reprezentuje poszczególne produkty (zabawki) w bazie danych. Każde wystąpienie Product
obiektu będzie odpowiadać wierszowi w tabeli relacyjnej bazy danych, a każda właściwość klasy Product będzie mapować na kolumnę w tabeli relacyjnej bazy danych. W dalszej części tego samouczka zapoznasz się z danymi produktu zawartymi w bazie danych.
Adnotacje danych
Być może zauważyliśmy, że niektóre elementy członkowskie klas mają atrybuty określające szczegóły dotyczące składowej, takie jak [ScaffoldColumn(false)]
. Są to adnotacje danych. Atrybuty adnotacji danych mogą opisywać sposób weryfikowania danych wejściowych użytkownika dla tego elementu członkowskiego, określania jego formatowania oraz określania sposobu modelowania podczas tworzenia bazy danych.
Context — Klasa
Aby rozpocząć korzystanie z klas dostępu do danych, należy zdefiniować klasę kontekstu. Jak wspomniano wcześniej, klasa kontekstu zarządza klasami jednostek (takimi jak Product
klasa i Category
klasa) i zapewnia dostęp do danych do bazy danych.
Ta procedura dodaje nową klasę kontekstu języka C# do folderu Models .
Kliknij prawym przyciskiem myszy folder Models , a następnie wybierz polecenie Dodaj ->Nowy element.
Zostanie wyświetlone okno dialogowe Dodaj nowy element.Wybierz pozycję Klasa w środkowym okienku, nadaj jej nazwę ProductContext.cs i kliknij przycisk Dodaj.
Zastąp domyślny kod zawarty w klasie następującym kodem:
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; } } }
Ten kod dodaje System.Data.Entity
przestrzeń nazw, aby mieć dostęp do wszystkich podstawowych funkcji platformy Entity Framework, która obejmuje możliwość wykonywania zapytań, wstawiania, aktualizowania i usuwania danych przez pracę z obiektami silnie typizowanym.
Klasa ProductContext
reprezentuje kontekst bazy danych produktu Entity Framework, który obsługuje pobieranie, przechowywanie i aktualizowanie Product
wystąpień klas w bazie danych. Klasa ProductContext
pochodzi z klasy bazowej dostarczonej DbContext
przez program Entity Framework.
Initializer, klasa
Aby zainicjować bazę danych przy pierwszym użyciu kontekstu, należy uruchomić logikę niestandardową. Pozwoli to na dodanie danych inicjujących do bazy danych, dzięki czemu można natychmiast wyświetlać produkty i kategorie.
Ta procedura dodaje nową klasę inicjatora języka C# do folderu Models .
Utwórz inny
Class
element w folderze Models i nadaj mu nazwę ProductDatabaseInitializer.cs.Zastąp domyślny kod zawarty w klasie następującym kodem:
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 widać w powyższym kodzie, po utworzeniu i zainicjowaniu Seed
bazy danych właściwość jest zastępowana i ustawiana. Po ustawieniu Seed
właściwości wartości z kategorii i produktów są używane do wypełniania bazy danych. Jeśli spróbujesz zaktualizować dane inicjujące, modyfikując powyższy kod po utworzeniu bazy danych, nie zobaczysz żadnych aktualizacji podczas uruchamiania aplikacji internetowej. Przyczyną jest użycie powyższego kodu implementacji DropCreateDatabaseIfModelChanges
klasy w celu rozpoznania, czy model (schemat) uległ zmianie przed zresetowaniem danych inicjujących. Jeśli w klasach jednostek i Product
nie zostaną wprowadzone Category
żadne zmiany, baza danych nie zostanie ponownie zainicjowana przy użyciu danych inicjalnych.
Uwaga
Jeśli chcesz, aby baza danych była odtwarzana za każdym razem, gdy uruchamiasz aplikację, możesz użyć DropCreateDatabaseAlways
klasy zamiast DropCreateDatabaseIfModelChanges
klasy . Jednak w tej serii samouczków użyj DropCreateDatabaseIfModelChanges
klasy .
Na tym etapie tego samouczka będziesz mieć folder Models z czterema nowymi klasami i jedną klasą domyślną:
Konfigurowanie aplikacji do korzystania z modelu danych
Po utworzeniu klas reprezentujących dane należy skonfigurować aplikację do używania klas. W pliku Global.asax dodasz kod, który inicjuje model. W pliku Web.config dodasz informacje, które informują aplikację, której bazy danych użyjesz do przechowywania danych reprezentowanych przez nowe klasy danych. Plik Global.asax może służyć do obsługi zdarzeń lub metod aplikacji. Plik Web.config umożliwia kontrolowanie konfiguracji aplikacji internetowej ASP.NET.
Aktualizowanie pliku Global.asax
Aby zainicjować modele danych podczas uruchamiania aplikacji, zaktualizujesz Application_Start
program obsługi w pliku Global.asax.cs .
Uwaga
W Eksplorator rozwiązań możesz wybrać plik Global.asax lub plik Global.asax.cs, aby edytować plik Global.asax.cs.
Dodaj następujący kod wyróżniony kolorem żółtym
Application_Start
do metody w pliku Global.asax.cs .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()); } } }
Uwaga
Przeglądarka musi obsługiwać kod HTML5, aby wyświetlić kod wyróżniony na żółto podczas wyświetlania tej serii samouczków w przeglądarce.
Jak pokazano w powyższym kodzie, po uruchomieniu aplikacji aplikacja określa inicjator, który będzie uruchamiany podczas pierwszego uzyskiwania dostępu do danych. Dwa dodatkowe przestrzenie nazw są wymagane do uzyskania dostępu Database
do obiektu i ProductDatabaseInitializer
obiektu.
Modyfikowanie pliku Web.Config
Mimo że program Entity Framework Code First wygeneruje bazę danych w domyślnej lokalizacji, gdy baza danych jest wypełniana danymi inicjanymi, dodanie własnych informacji o połączeniu do aplikacji daje kontrolę nad lokalizacją bazy danych. To połączenie z bazą danych określa się przy użyciu parametrów połączenia w pliku Web.config aplikacji w katalogu głównym projektu. Dodając nowe parametry połączenia, można skierować lokalizację bazy danych (wingtiptoys.mdf) do skompilowania w katalogu danych aplikacji (App_Data) zamiast lokalizacji domyślnej. Wprowadzenie tej zmiany umożliwi znalezienie i sprawdzenie pliku bazy danych w dalszej części tego samouczka.
W Eksplorator rozwiązań znajdź i otwórz plik Web.config.
Dodaj parametry połączenia wyróżnione kolorem żółtym do
<connectionStrings>
sekcji pliku Web.config w następujący sposób:<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>
Gdy aplikacja zostanie uruchomiona po raz pierwszy, skompiluje bazę danych w lokalizacji określonej przez parametry połączenia. Ale przed uruchomieniem aplikacji skompilujmy ją najpierw.
Kompilowanie aplikacji
Aby upewnić się, że wszystkie klasy i zmiany aplikacji internetowej działają, należy skompilować aplikację.
Z menu Debuguj wybierz pozycję Kompiluj WingtipToys.
Zostanie wyświetlone okno Dane wyjściowe . Jeśli wszystko poszło dobrze, zostanie wyświetlony komunikat o powodzeniu .
Jeśli wystąpi błąd, sprawdź ponownie powyższe kroki. Informacje w oknie Dane wyjściowe wskazują, który plik ma problem i gdzie w pliku jest wymagana zmiana. Te informacje umożliwią określenie, która część powyższych kroków należy przejrzeć i naprawić w projekcie.
Podsumowanie
W tym samouczku serii utworzono model danych, a także dodano kod, który będzie używany do inicjowania i rozmieszczania bazy danych. Skonfigurowano również aplikację do używania modeli danych podczas uruchamiania aplikacji.
W następnym samouczku zaktualizujesz interfejs użytkownika, dodasz nawigację i pobierzesz dane z bazy danych. Spowoduje to automatyczne utworzenie bazy danych na podstawie klas jednostek utworzonych w tym samouczku.
Dodatkowe zasoby
Omówienie programu Entity Framework
Przewodnik dla początkujących dotyczący platformy Entity Framework ADO.NET
Code First Development with Entity Framework Code FirstRelationships Fluent API
Adnotacje do danych Code First
Ulepszenia produktywności dla platformy Entity Framework