Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
av Microsoft
Målet med den här självstudien är att förklara en metod för att skapa modellklasser för en ASP.NET MVC-applikation. I den här självstudien lär du dig hur du skapar modellklasser och utför databasåtkomst genom att dra nytta av Microsoft LINQ till SQL.
Målet med den här handledningen är att förklara en metod för att skapa modellklasser för en ASP.NET MVC-applikation. I den här självstudien får du lära dig hur du skapar modellklasser och utför databasåtkomst genom att dra nytta av Microsoft LINQ till SQL
I den här handledningen skapar vi ett grundläggande filmdatabasprogram. Vi börjar med att skapa filmdatabasprogrammet på det snabbaste och enklaste sättet. Vi utför all vår dataåtkomst direkt från våra kontrolleroperationer.
Sedan får du lära dig hur du använder Depotmönstret. Att använda Repository-mönstret kräver lite mer arbete. Fördelen med att använda det här mönstret är dock att du kan skapa program som kan ändras och enkelt kan testas.
Vad är en modellklass?
En MVC-modell innehåller all programlogik som inte finns i en MVC-vy eller MVC-styrenhet. I synnerhet innehåller en MVC-modell all logik för programverksamhet och dataåtkomst.
Du kan använda en mängd olika tekniker för att implementera dataåtkomstlogik. Du kan till exempel skapa dina dataåtkomstklasser med hjälp av klasserna Microsoft Entity Framework, NHibernate, Subsonic eller ADO.NET.
I den här handledningen använder jag LINQ till SQL för att fråga ut och uppdatera databasen. LINQ till SQL ger dig en mycket enkel metod för att interagera med en Microsoft SQL Server-databas. Det är dock viktigt att förstå att ASP.NET MVC-ramverket inte är kopplat till LINQ till SQL på något sätt. ASP.NET MVC är kompatibelt med all dataåtkomstteknik.
Skapa en filmdatabas
I den här självstudien – för att illustrera hur du kan skapa modellklasser – skapar vi ett enkelt filmdatabasprogram. Det första steget är att skapa en ny databas. Högerklicka på mappen App_Data i Solution Explorer-fönstret och välj menyalternativet Lägg till, Nytt objekt. Välj SQL Server Database-mallen , ge den namnet MoviesDB.mdf och klicka på knappen Lägg till (se bild 1).
Bild 01: Lägga till en ny SQL Server-databas (Klicka om du vill visa en bild i full storlek)
När du har skapat den nya databasen kan du öppna databasen genom att dubbelklicka på filen MoviesDB.mdf i mappen App_Data. Om du dubbelklickar på filen MoviesDB.mdf öppnas fönstret ServerUtforskaren (se bild 2).
Fönstret ServerUtforskaren kallas för Fönstret Databasutforskaren när du använder Visual Web Developer.
Bild 02: Använda fönstret Serverutforskaren (Klicka om du vill visa en bild i full storlek)
Vi måste lägga till en tabell i vår databas som representerar våra filmer. Högerklicka på mappen Tabeller och välj menyalternativet Lägg till ny tabell. Om du väljer det här menyalternativet öppnas tabelldesignern (se bild 3).
Bild 03: Tabelldesignern (Klicka om du vill visa en bild i full storlek)
Vi måste lägga till följande kolumner i vår databastabell:
| Kolumnnamn | Datatyp | Tillåt null-värden |
|---|---|---|
| Id | Int | Falsk |
| Titel | Nvarchar(200) | Falsk |
| Direktör | Nvarchar(50) | Falsk |
Du måste göra två särskilda saker i kolumnen ID. Först måste du markera ID-kolumnen som en primär nyckelkolumn genom att välja kolumnen i Tabelldesignern och klicka på ikonen för en nyckel. LINQ till SQL kräver att du anger dina primära nyckelkolumner när du utför infogningar eller uppdateringar mot databasen.
Därefter måste du markera kolumnen ID som en identitetskolumn genom att tilldela värdet Ja till egenskapen Is Identity (se bild 3). En identitetskolumn är en kolumn som tilldelas ett nytt nummer automatiskt när du lägger till en ny rad med data i en tabell.
Skapa LINQ till SQL-klasser
Vår MVC-modell innehåller LINQ till SQL-klasser som representerar tblMovie-databastabellen. Det enklaste sättet att skapa dessa LINQ-till SQL-klasser är att högerklicka på mappen Modeller, välja Lägg till, Nytt objekt, välja mallen LINQ till SQL-klasser, ge klasserna namnet Movie.dbml och klicka på knappen Lägg till (se bild 4).
Bild 04: Skapa LINQ till SQL-klasser (Klicka om du vill visa en bild i full storlek)
Direkt efter att du har skapat Movie LINQ till SQL-klasser visas objektrelationsdesignern. Du kan dra databastabeller från fönstret Server-explorern till Objektrelationsdesignern för att skapa LINQ till SQL-klasser som representerar specifika databastabeller. Vi måste lägga till tblMovie-databastabellen i objektrelationsdesignern (se bild 5).
Bild 05: Använda objektrelationsdesignern (klicka om du vill visa en bild i full storlek)
Som standard skapar objektrelationsdesignern en klass med samma namn som databastabellen som du drar till designern. Men vi vill inte anropa vår klass tblMovie. Klicka därför på namnet på klassen i designern och ändra namnet på klassen till Film.
Kom slutligen ihåg att klicka på knappen Spara (bilden på disketten) för att spara LINQ i SQL-klasser. Annars genereras inte LINQ-till SQL-klasserna av objektrelationsdesignern.
Använda LINQ till SQL i en kontrollantåtgärd
Nu när vi har våra LINQ till SQL-klasser kan vi använda dessa klasser för att hämta data från databasen. I det här avsnittet får du lära dig hur du använder LINQ till SQL-klasser direkt i en kontrollantåtgärd. Vi visar listan över filmer från tblMovies-databastabellen i en MVC-vy.
Först måste vi ändra klassen HomeController. Den här klassen finns i mappen Controllers i ditt program. Ändra klassen så att den ser ut som klassen i Listning 1.
Lista 1 – Controllers\HomeController.cs
using System.Linq;
using System.Web.Mvc;
using MvcApplication1.Models;
namespace MvcApplication1.Controllers
{
[HandleError]
public class HomeController : Controller
{
public ActionResult Index()
{
var dataContext = new MovieDataContext();
var movies = from m in dataContext.Movies
select m;
return View(movies);
}
}
}
Åtgärden Index() i Listning 1 använder klassen LINQ till SQL DataContext () MovieDataContextför att representera MoviesDB databasen. Klassen MoveDataContext genererades av Visual Studio Object Relational Designer.
En LINQ-fråga utförs mot DataContext för att hämta alla filmer från databastabellen tblMovies . Listan över filmer tilldelas till en lokal variabel med namnet movies. Slutligen skickas listan över filmer till vyn via visningsdata.
För att kunna visa filmerna måste vi sedan ändra indexvyn. Du hittar indexvyn i Views\Home\ mappen . Uppdatera indexvyn så att den ser ut som vyn i Listning 2.
Lista 2 – Views\Home\Index.aspx
<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="MvcApplication1.Views.Home.Index" %>
<%@ Import Namespace="MvcApplication1.Models" %>
<asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">
<ul>
<% foreach (Movie m in (IEnumerable)ViewData.Model)
{ %>
<li> <%= m.Title %> </li>
<% } %>
</ul>
</asp:Content>
Observera att den ändrade indexvyn innehåller ett <%@ import namespace %> direktiv överst i vyn. Det här direktivet importerar MvcApplication1.Models namespace. Vi behöver den här namnrymden model för att kunna arbeta med klasserna – i synnerhet Movie klassen – i vyn.
Vyn i Listning 2 innehåller en foreach loop som itererar genom alla objekt som representeras av egenskapen ViewData.Model . Värdet för egenskapen Title visas för varje movie.
Observera att värdet för egenskapen är konverterat ViewData.Model till en IEnumerable. Detta är nödvändigt för att loopa igenom innehållet i ViewData.Model. Ett annat alternativ här är att skapa en starkt typad view. När du skapar en starkt typad view konverterar du ViewData.Model-egenskapen till en viss typ i en vys kod-behind-klass.
Om du kör programmet när du har modifierat HomeController klassen och indexvyn får du en tom sida. Du får en tom sida eftersom det inte finns några poster i databastabellen tblMovies för filmer.
Om du vill lägga till poster i databastabellen tblMovies högerklickar du på databastabellen tblMovies i fönstret ServerUtforskaren (Databasutforskaren i Visual Web Developer) och väljer menyalternativet Visa tabelldata. Du kan infoga movie poster med hjälp av det rutnät som visas (se figur 6).
Bild 06: Infoga filmer(Klicka om du vill visa en bild i full storlek)
När du har lagt till några databasposter i tblMovies tabellen och kört programmet visas sidan i bild 7. Alla filmdatabasposter visas i en punktlista.
Bild 07: Visa filmer med indexvyn(Klicka om du vill visa en bild i full storlek)
Använda lagringsplatsens mönster
I föregående avsnitt använde vi LINQ till SQL-klasser direkt i en kontrollantåtgärd. Vi använde MovieDataContext klassen direkt från kontrollantåtgärden Index() . Det är inget fel med att göra detta när det gäller ett enkelt program. Men att arbeta direkt med LINQ till SQL i en kontrollantklass skapar problem när du behöver skapa ett mer komplext program.
Att använda LINQ till SQL i en kontrollantklass gör det svårt att växla dataåtkomsttekniker i framtiden. Du kan till exempel välja att växla från att använda Microsoft LINQ till SQL till att använda Microsoft Entity Framework som dataåtkomstteknik. I så fall skulle du behöva skriva om varje kontrollant som har åtkomst till databasen i ditt program.
Att använda LINQ till SQL i en kontrollantklass gör det också svårt att skapa enhetstester för ditt program. Normalt vill du inte interagera med en databas när du utför enhetstester. Du vill använda enhetstesterna för att testa programlogik och inte databasservern.
För att skapa ett MVC-program som är mer anpassningsbart till framtida ändringar och som enklare kan testas bör du överväga att använda mönstret Lagringsplats. När du använder mönstret Lagringsplats skapar du en separat lagringsplatsklass som innehåller all databasåtkomstlogik.
När du skapar lagringsplatsklassen skapar du ett gränssnitt som representerar alla metoder som används av lagringsplatsens klass. I dina kontrollanter skriver du koden mot gränssnittet i stället för lagringsplatsen. På så sätt kan du implementera lagringsplatsen med hjälp av olika dataåtkomsttekniker i framtiden.
Gränssnittet i Listning 3 heter IMovieRepository och representerar en enda metod med namnet ListAll().
Lista 3 – Models\IMovieRepository.cs
using System.Collections.Generic;
namespace MvcApplication1.Models
{
public interface IMovieRepository
{
IList<Movie> ListAll();
}
}
Lagringsplatsklassen i List 4 implementerar IMovieRepository gränssnittet. Observera att den innehåller en metod med namnet ListAll() som motsvarar den metod som krävs av IMovieRepository gränssnittet.
Lista 4 – Models\MovieRepository.cs
using System.Collections.Generic;
using System.Linq;
namespace MvcApplication1.Models
{
public class MovieRepository : IMovieRepository
{
private MovieDataContext _dataContext;
public MovieRepository()
{
_dataContext = new MovieDataContext();
}
#region IMovieRepository Members
public IList<Movie> ListAll()
{
var movies = from m in _dataContext.Movies
select m;
return movies.ToList();
}
#endregion
}
}
Slutligen använder klassen i Listning 5 Repository-mönstret. Den använder inte längre LINQ till SQL-klasser direkt.
Lista 5 – Controllers\MoviesController.cs
using System.Web.Mvc;
using MvcApplication1.Models;
namespace MvcApplication1.Controllers
{
public class MoviesController : Controller
{
private IMovieRepository _repository;
public MoviesController() : this(new MovieRepository())
{
}
public MoviesController(IMovieRepository repository)
{
_repository = repository;
}
public ActionResult Index()
{
return View(_repository.ListAll());
}
}
}
Observera att MoviesController klassen i Listning 5 har två konstruktorer. Den första konstruktorn, den parameterlösa konstruktorn, anropas när programmet körs. Den här konstruktorn skapar en instans av MovieRepository klassen och skickar den till den andra konstruktorn.
Den andra konstruktorn har en enda parameter: en IMovieRepository parameter. Den här konstruktorn tilldelar helt enkelt värdet för parametern till ett fält på klassnivå med namnet _repository.
Klassen MoviesController utnyttjar ett mönster för programvarudesign som kallas beroendeinmatningsmönstret. I synnerhet använder den något som kallas konstruktorberoendeinmatning. Du kan läsa mer om det här mönstret genom att läsa följande artikel av Martin Fowler:
http://martinfowler.com/articles/injection.html
Observera att all kod i MoviesController klassen (med undantag för den första konstruktorn) interagerar med IMovieRepository gränssnittet i stället för den faktiska MovieRepository klassen. Koden interagerar med ett abstrakt gränssnitt i stället för en konkret implementering av gränssnittet.
Om du vill ändra dataåtkomsttekniken som används av programmet kan du helt enkelt implementera IMovieRepository gränssnittet med en klass som använder den alternativa databasåtkomsttekniken. Du kan till exempel skapa en EntityFrameworkMovieRepository klass eller en SubSonicMovieRepository klass. Eftersom kontrollantklassen är programmerad mot gränssnittet kan du skicka en ny implementering av IMovieRepository till kontrollantklassen och klassen fortsätter att fungera.
Om du vill testa MoviesController klassen kan du dessutom skicka en falsk filmlagringsplatsklass till HomeController. Du kan implementera IMovieRepository klassen med en klass som faktiskt inte har åtkomst till databasen, men som innehåller alla nödvändiga metoder i IMovieRepository gränssnittet. På så sätt kan du enhetstesta MoviesController klassen utan att komma åt en riktig databas.
Sammanfattning
Målet med den här handledningen var att visa hur du kan skapa MVC-modellklasser genom att utnyttja Microsoft LINQ till SQL. Vi undersökte två strategier för att visa databasdata i ett ASP.NET MVC-program. Först skapade vi LINQ till SQL-klasser och använde klasserna direkt i en kontrollantåtgärd. Med LINQ till SQL-klasser i en kontrollant kan du snabbt och enkelt visa databasdata i ett MVC-program.
Därefter utforskade vi en något svårare, men definitivt mer dygdig, sökväg för att visa databasdata. Vi utnyttjade mönstret Lagringsplats och placerade all vår databasåtkomstlogik i en separat lagringsplatsklass. I vår kontrollant skrev vi all vår kod mot ett gränssnitt i stället för en konkret klass. Fördelen med Lagringsmönstret är att det gör att vi enkelt kan ändra databasåtkomsttekniker i framtiden och det gör att vi enkelt kan testa våra kontrollklasser.