Udostępnij za pośrednictwem


Tworzenie klas modeli za pomocą modelu LINQ to SQL (VB)

autor: Microsoft

Pobierz plik PDF

Celem tego samouczka jest wyjaśnienie jednej metody tworzenia klas modeli dla aplikacji ASP.NET MVC. Z tego samouczka dowiesz się, jak tworzyć klasy modeli i uzyskiwać dostęp do bazy danych, korzystając z usługi Microsoft LINQ to SQL.

Celem tego samouczka jest wyjaśnienie jednej metody tworzenia klas modeli dla aplikacji ASP.NET MVC. Z tego samouczka dowiesz się, jak tworzyć klasy modeli i uzyskiwać dostęp do bazy danych, korzystając z usługi Microsoft LINQ to SQL.

W tym samouczku utworzymy podstawową aplikację bazy danych Movie. Zaczynamy od utworzenia aplikacji bazy danych Movie w najszybszy i najprostszy możliwy sposób. Przeprowadzamy cały dostęp do danych bezpośrednio z naszych akcji kontrolera.

Następnie dowiesz się, jak używać wzorca repozytorium. Użycie wzorca repozytorium wymaga nieco więcej pracy. Jednak zaletą przyjęcia tego wzorca jest to, że umożliwia tworzenie aplikacji, które można dostosować do zmian i można je łatwo przetestować.

Co to jest klasa modelu?

Model MVC zawiera całą logikę aplikacji, która nie znajduje się w widoku MVC lub kontrolerze MVC. W szczególności model MVC zawiera całą logikę biznesową aplikacji i dostęp do danych.

Do zaimplementowania logiki dostępu do danych można użyć różnych technologii. Możesz na przykład skompilować klasy dostępu do danych przy użyciu klas Microsoft Entity Framework, NHibernate, Subsonic lub ADO.NET.

W tym samouczku używam LINQ to SQL do wykonywania zapytań i aktualizowania bazy danych. LINQ to SQL zapewnia bardzo łatwą metodę interakcji z bazą danych microsoft SQL Server. Jednak ważne jest, aby zrozumieć, że struktura ASP.NET MVC nie jest powiązana z LINQ to SQL w żaden sposób. ASP.NET MVC jest zgodny z dowolną technologią dostępu do danych.

Tworzenie bazy danych filmów

W tym samouczku — w celu zilustrowania sposobu tworzenia klas modeli — tworzymy prostą aplikację bazy danych Movie. Pierwszym krokiem jest utworzenie nowej bazy danych. Kliknij prawym przyciskiem myszy folder App_Data w oknie Eksplorator rozwiązań i wybierz opcję menu Dodaj, Nowy element. Wybierz szablon bazy danych SQL Server, nadaj mu nazwę MoviesDB.mdf, a następnie kliknij przycisk Dodaj (zobacz Rysunek 1).

Dodawanie nowej bazy danych SQL Server

Rysunek 01. Dodawanie nowej bazy danych SQL Server (kliknij, aby wyświetlić obraz pełnowymiarowy)

Po utworzeniu nowej bazy danych możesz otworzyć bazę danych, klikając dwukrotnie plik MoviesDB.mdf w folderze App_Data. Dwukrotne kliknięcie pliku MoviesDB.mdf powoduje otwarcie okna Eksploratora serwera (zobacz Rysunek 2).

Okno Eksploratora serwera jest nazywane oknem Eksplorator bazy danych podczas korzystania z programu Visual Web Developer.

Zrzut ekranu przedstawiający okno Eksploratora serwera, które pokazuje, że folder Tables został wyróżniony w hierarchii folderów.

Rysunek 02. Korzystanie z okna Eksploratora serwera (kliknij, aby wyświetlić obraz pełnowymiarowy)

Musimy dodać jedną tabelę do naszej bazy danych, która reprezentuje nasze filmy. Kliknij prawym przyciskiem myszy folder Tables i wybierz opcję menu Dodaj nową tabelę. Wybranie tej opcji menu powoduje otwarcie Projektant Tabeli (zobacz Rysunek 3).

Zrzut ekranu przedstawiający okno programu Microsoft Visual Studio z funkcją Tabela Projektant.

Rysunek 03. Projektant tabeli (kliknij, aby wyświetlić obraz pełnowymiarowy)

Musimy dodać następujące kolumny do tabeli bazy danych:

Nazwa kolumny Typ danych Zezwalaj na wartości null
Id int Fałsz
Tytuł Nvarchar(200) Fałsz
Dyrektor Nvarchar(50) Fałsz

Musisz wykonać dwie specjalne czynności w kolumnie Id. Najpierw musisz oznaczyć kolumnę Id jako kolumnę klucza podstawowego, wybierając kolumnę w tabeli Projektant i klikając ikonę klucza. LINQ to SQL wymaga określenia kolumn klucza podstawowego podczas wstawiania lub aktualizacji bazy danych.

Następnie należy oznaczyć kolumnę Id jako kolumnę Tożsamość, przypisując wartość Tak do właściwości Is Identity (Rysunek 3). Kolumna Tożsamość to kolumna, która jest przypisywana do nowej liczby automatycznie po dodaniu nowego wiersza danych do tabeli.

Po wprowadzeniu tych zmian zapisz tabelę o nazwie tblFilm. Tabelę można zapisać, klikając przycisk Zapisz.

Tworzenie klas LINQ to SQL

Nasz model MVC będzie zawierać LINQ to SQL klasy reprezentujące tabelę bazy danych tblFilm. Najprostszym sposobem utworzenia tych klas LINQ to SQL jest kliknięcie prawym przyciskiem myszy folderu Models, wybranie pozycji Dodaj, Nowy element, wybranie szablonu klasy LINQ to SQL, nadanie klasom nazwy Movie.dbml i kliknięcie przycisku Dodaj (zobacz Rysunek 4).

Tworzenie klas LINQ to SQL

Rysunek 04. Tworzenie klas LINQ to SQL (kliknij, aby wyświetlić obraz pełnowymiarowy)

Natychmiast po utworzeniu klas LINQ to SQL filmowych zostanie wyświetlony Object Relational Designer. Tabele baz danych można przeciągnąć z okna Eksploratora serwera na Object Relational Designer, aby utworzyć klasy LINQ to SQL reprezentujące określone tabele bazy danych. Musimy dodać tabelę bazy danych tblFilm do Object Relational Designer (zobacz Rysunek 4).

Korzystanie z Object Relational Designer

Rysunek 05. Używanie Object Relational Designer (kliknij, aby wyświetlić obraz pełnowymiarowy)

Domyślnie Object Relational Designer tworzy klasę o tej samej nazwie co tabela bazy danych, którą przeciągniesz na Projektant. Nie chcemy jednak wywoływać klasy tblFilm. W związku z tym kliknij nazwę klasy w Projektant i zmień nazwę klasy na Movie.

Na koniec pamiętaj, aby kliknąć przycisk Zapisz (obraz dyskietki), aby zapisać klasy LINQ to SQL. W przeciwnym razie klasy LINQ to SQL nie będą generowane przez Object Relational Designer.

Używanie LINQ to SQL w akcji kontrolera

Teraz, gdy mamy nasze klasy LINQ to SQL, możemy użyć tych klas do pobierania danych z bazy danych. W tej sekcji dowiesz się, jak używać klas LINQ to SQL bezpośrednio w ramach akcji kontrolera. W widoku MVC zostanie wyświetlona lista filmów z tabeli bazy danych tblFilms.

Najpierw musimy zmodyfikować klasę HomeController. Tę klasę można znaleźć w folderze Kontrolery aplikacji. Zmodyfikuj klasę tak, aby wyglądała jak klasa na liście 1.

Lista 1 — Controllers\HomeController.vb

<HandleError()> _
Public Class HomeController

     Inherits System.Web.Mvc.Controller

     Function Index()
          Dim dataContext As New MovieDataContext()
          Dim movies = From m In dataContext.Movies _
               Select m
          return View(movies)
     End Function
End Class

Akcja Index() na liście 1 używa klasy LINQ to SQL DataContext (MovieDataContext) do reprezentowania bazy danych MoviesDB. Klasa MoveDataContext została wygenerowana przez program Visual Studio Object Relational Designer.

Zapytanie LINQ jest wykonywane względem obiektu DataContext w celu pobrania wszystkich filmów z tabeli bazy danych tblFilms. Lista filmów jest przypisywana do zmiennej lokalnej o nazwie movies. Na koniec lista filmów jest przekazywana do widoku za pośrednictwem danych widoku.

Aby pokazać filmy, musimy zmodyfikować widok Indeks. Widok Indeks można znaleźć w folderze Views\Home\. Zaktualizuj widok Indeks, tak aby wyglądał jak widok na liście 2.

Lista 2 — Views\Home\Index.aspx

<%@ Page Language="VB" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="false" CodeBehind="Index.aspx.vb" Inherits="MvcApplication1.Index" %>
<%@ Import Namespace="MvcApplication1" %>
<asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">

<ul>
<%  For Each m As Movie In ViewData.Model%>
    <li><%= m.Title %></li>
<% Next%>
</ul>
</asp:Content>

Zwróć uwagę, że zmodyfikowany widok indeksu zawiera dyrektywę <%@ import przestrzeni nazw %> w górnej części widoku. Ta dyrektywa importuje przestrzeń nazw MvcApplication1. Potrzebujemy tej przestrzeni nazw, aby pracować z klasami modeli — w szczególności klasą Movie — w widoku.

Widok w liście 2 zawiera pętlę Dla każdego, która iteruje wszystkie elementy reprezentowane przez właściwość ViewData.Model. Wartość właściwości Title jest wyświetlana dla każdego filmu.

Zwróć uwagę, że wartość właściwości ViewData.Model jest rzutowana na wartość IEnumerable. Jest to konieczne w celu pętli zawartości elementu ViewData.Model. Inną opcją jest utworzenie silnie typizowanego widoku. Podczas tworzenia silnie typizowanego widoku należy rzutować właściwość ViewData.Model na określony typ w klasie kodu w widoku.

Jeśli uruchomisz aplikację po zmodyfikowaniu klasy HomeController i widoku Indeks, zostanie wyświetlona pusta strona. Zostanie wyświetlona pusta strona, ponieważ w tabeli bazy danych tblFilms nie ma żadnych rekordów filmowych.

Aby dodać rekordy do tabeli bazy danych tblFilms, kliknij prawym przyciskiem myszy tabelę bazy danych tblFilms w oknie Eksplorator serwera (okno Eksplorator bazy danych w programie Visual Web Developer) i wybierz opcję menu Pokaż dane tabeli. Rekordy filmów można wstawić przy użyciu wyświetlonej siatki (zobacz Rysunek 5).

Wstawianie filmów

Rysunek 06. Wstawianie filmów (kliknij, aby wyświetlić obraz pełnowymiarowy)

Po dodaniu niektórych rekordów bazy danych do tabeli tblFilms i uruchomieniu aplikacji zostanie wyświetlona strona na rysunku 7. Wszystkie rekordy bazy danych filmów są wyświetlane na liście punktowanej.

Wyświetlanie filmów z widokiem indeksu

Rysunek 07. Wyświetlanie filmów z widokiem indeksu(Kliknij, aby wyświetlić obraz pełnowymiarowy)

Korzystanie ze wzorca repozytorium

W poprzedniej sekcji użyliśmy klas LINQ to SQL bezpośrednio w ramach akcji kontrolera. Użyliśmy klasy MovieDataContext bezpośrednio z akcji kontrolera Index(). W przypadku prostej aplikacji nie ma nic złego. Jednak praca bezpośrednio z LINQ to SQL w klasie kontrolera powoduje problemy, gdy trzeba utworzyć bardziej złożoną aplikację.

Użycie LINQ to SQL w klasie kontrolera utrudnia przełączanie technologii dostępu do danych w przyszłości. Możesz na przykład zdecydować się na przejście z używania platformy Microsoft LINQ to SQL do korzystania z programu Microsoft Entity Framework jako technologii dostępu do danych. W takim przypadku należy ponownie napisać każdy kontroler, który uzyskuje dostęp do bazy danych w aplikacji.

Użycie LINQ to SQL w klasie kontrolera utrudnia również kompilowanie testów jednostkowych dla aplikacji. Zwykle nie chcesz wchodzić w interakcję z bazą danych podczas wykonywania testów jednostkowych. Chcesz użyć testów jednostkowych do przetestowania logiki aplikacji, a nie serwera bazy danych.

Aby utworzyć aplikację MVC, która jest bardziej dostosowywalna do przyszłych zmian i którą można łatwiej przetestować, należy rozważyć użycie wzorca repozytorium. W przypadku korzystania ze wzorca repozytorium należy utworzyć oddzielną klasę repozytorium zawierającą całą logikę dostępu do bazy danych.

Podczas tworzenia klasy repozytorium tworzony jest interfejs reprezentujący wszystkie metody używane przez klasę repozytorium. W ramach kontrolerów piszesz kod względem interfejsu zamiast repozytorium. W ten sposób można zaimplementować repozytorium przy użyciu różnych technologii dostępu do danych w przyszłości.

Interfejs w liście 3 nosi nazwę IRepository i reprezentuje jedną metodę o nazwie ListAll().

Lista 3 — Models\IMovieRepository.vb

Public Interface IMovieRepository
     Function ListAll() As IList(Of Movie)
End Interface

Klasa repozytorium w pozycji List 4 implementuje interfejs IRepository. Zwróć uwagę, że zawiera metodę o nazwie ListAll(), która odpowiada metodzie wymaganej przez interfejs IRepository.

Lista 4 — Models\MovieRepository.vb

Public Class MovieRepository Implements IMovieRepository
         Private _dataContext As MovieDataContext

         Public Sub New()
              _dataContext = New MovieDataContext()
         End Sub

         Public Function ListAll() As IList(Of Movie) Implements IMovieRepository.ListAll
              Dim movies = From m In _dataContext.Movies _
                   Select m
              Return movies.ToList()
         End Function
End Class

Na koniec klasa MoviesController w liście List 5 używa wzorca repozytorium. Nie używa już klas LINQ to SQL bezpośrednio.

Lista 5 — Controllers\MoviesController.vb

using System.Web.Mvc;
using MvcApplication1.Models;

namespace MvcApplication1.Controllers
{
    Public Class MoviesController 
        Inherits System.Web.Mvc.Controller

             Private _repository As IMovieRepository

             Sub New()
                  Me.New(New MovieRepository())
             End Sub

             Sub New(ByVal repository As IMovieRepository)
                  _repository = repository
             End Sub

             Function Index()
                  Return View(_repository.ListAll())
             End Function
    End Class
}

Zwróć uwagę, że klasa MoviesController w listu 5 ma dwa konstruktory. Pierwszy konstruktor, konstruktor bez parametrów, jest wywoływany, gdy aplikacja jest uruchomiona. Ten konstruktor tworzy wystąpienie klasy MovieRepository i przekazuje go do drugiego konstruktora.

Drugi konstruktor ma jeden parametr: parametr IRepository. Ten konstruktor po prostu przypisuje wartość parametru do pola na poziomie klasy o nazwie _repository.

Klasa MoviesController korzysta ze wzorca projektowego oprogramowania nazywanego wzorcem wstrzykiwania zależności. W szczególności używa czegoś o nazwie Wstrzykiwanie zależności konstruktora. Więcej informacji na temat tego wzorca można przeczytać w następującym artykule Martin Fowler:

http://martinfowler.com/articles/injection.html

Zwróć uwagę, że cały kod w klasie MoviesController (z wyjątkiem pierwszego konstruktora) współdziała z interfejsem IRepository zamiast rzeczywistej klasy MovieRepository. Kod współdziała z abstrakcyjnym interfejsem zamiast konkretnej implementacji interfejsu.

Jeśli chcesz zmodyfikować technologię dostępu do danych używaną przez aplikację, możesz po prostu zaimplementować interfejs IRepository z klasą korzystającą z alternatywnej technologii dostępu do bazy danych. Można na przykład utworzyć klasę EntityFrameworkRepositoryRepository lub klasę SubSonicRepositoryRepository. Ponieważ klasa kontrolera jest programowana względem interfejsu, można przekazać nową implementację IRepository do klasy kontrolera, a klasa będzie nadal działać.

Ponadto jeśli chcesz przetestować klasę MoviesController, możesz przekazać klasę fałszywego repozytorium filmów do klasy MoviesController. Klasę IRepository można zaimplementować przy użyciu klasy, która nie uzyskuje dostępu do bazy danych, ale zawiera wszystkie wymagane metody interfejsu IRepository. W ten sposób można przetestować klasę MoviesController bez uzyskiwania dostępu do prawdziwej bazy danych.

Podsumowanie

Celem tego samouczka było pokazanie, jak można tworzyć klasy modeli MVC, korzystając z usługi Microsoft LINQ to SQL. Zbadaliśmy dwie strategie wyświetlania danych bazy danych w aplikacji ASP.NET MVC. Najpierw utworzyliśmy klasy LINQ to SQL i używaliśmy klas bezpośrednio w ramach akcji kontrolera. Używanie klas LINQ to SQL w kontrolerze umożliwia szybkie i łatwe wyświetlanie danych bazy danych w aplikacji MVC.

Następnie zbadaliśmy nieco trudniejsze, ale zdecydowanie bardziej cnotliwe ścieżki do wyświetlania danych bazy danych. Skorzystaliśmy ze wzorca repozytorium i umieściliśmy całą logikę dostępu do bazy danych w oddzielnej klasie repozytorium. W naszym kontrolerze napisaliśmy cały nasz kod względem interfejsu zamiast konkretnej klasy. Zaletą wzorca repozytorium jest to, że umożliwia nam łatwe zmienianie technologii dostępu do bazy danych w przyszłości i umożliwia nam łatwe testowanie klas kontrolerów.