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

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 jest 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, które pokazuje funkcję Projektant tabeli.

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.

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 5).

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 tblMovie. 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.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);
          }
     }
}

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

Zapytanie LINQ jest wykonywane względem elementu DataContext w celu pobrania wszystkich filmów z tblMovies tabeli bazy danych. 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="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>

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

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

Zwróć uwagę, że wartość ViewData.Model właściwości jest rzutowania na IEnumerablewartość . Jest to konieczne w celu pętli przez zawartość elementu ViewData.Model. Inną opcją jest utworzenie silnie typizowanego viewelementu . Podczas tworzenia silnie typizowanego viewobiektu należy rzutować ViewData.Model właściwość do określonego typu w klasie kodu w widoku.

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

Aby dodać rekordy do tblMovies tabeli bazy danych, kliknij prawym przyciskiem myszy tabelę tblMovies bazy danych w oknie Eksplorator serwera (okno Eksplorator bazy danych w programie Visual Web Developer) i wybierz opcję menu Pokaż dane tabeli. Możesz wstawić movie rekordy przy użyciu wyświetlonej siatki (zobacz Rysunek 6).

Wstawianie filmów

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

Po dodaniu rekordów bazy danych do tabeli i uruchomieniu aplikacji zobaczysz stronę na rysunku tblMovies 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 LINQ to SQL klas bezpośrednio w ramach akcji kontrolera. Użyliśmy MovieDataContext klasy bezpośrednio z Index() akcji kontrolera. Nie ma nic złego w tym przypadku w przypadku prostej aplikacji. 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. Na przykład możesz 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 interakcje 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 dostosowywana do przyszłych zmian i którą można łatwiej przetestować, należy rozważyć użycie wzorca repozytorium. Korzystając ze wzorca repozytorium, należy utworzyć oddzielną klasę repozytorium zawierającą całą logikę dostępu do bazy danych.

Podczas tworzenia klasy repozytorium należy utworzyć interfejs, który reprezentuje wszystkie metody używane przez klasę repozytorium. W ramach kontrolerów napiszesz kod względem interfejsu zamiast repozytorium. Dzięki temu 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ę IMovieRepository i reprezentuje jedną metodę o nazwie ListAll().

Lista 3 — Models\IMovieRepository.cs

using System.Collections.Generic;
namespace MvcApplication1.Models
{
     public interface IMovieRepository
     {
          IList<Movie> ListAll();
     }
}

Klasa repozytorium na liście 4 implementuje IMovieRepository interfejs. Zwróć uwagę, że zawiera metodę o nazwie ListAll() odpowiadającą metodzie wymaganej IMovieRepository przez interfejs.

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

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

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

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

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

Klasa MoviesController korzysta ze wzorca projektowego oprogramowania o nazwie Wzorzec 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 Autorstwa Martina Fowlera:

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

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

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

Ponadto, jeśli chcesz przetestować klasę MoviesController , możesz przekazać do klasy fałszywego repozytorium filmów klasę HomeController. Klasę IMovieRepository można zaimplementować za pomocą klasy, która nie uzyskuje dostępu do bazy danych, ale zawiera wszystkie wymagane metody interfejsu IMovieRepository . Dzięki temu można testować klasę jednostkowo MoviesController bez uzyskiwania dostępu do rzeczywistej bazy danych.

Podsumowanie

Celem tego samouczka było zademonstrowanie sposobu tworzenia klas modeli MVC przy użyciu usługi Microsoft LINQ to SQL. Przeanalizowaliśmy dwie strategie wyświetlania danych bazy danych w aplikacji MVC ASP.NET. Najpierw utworzyliśmy LINQ to SQL klasy i użyliśmy klas bezpośrednio w ramach akcji kontrolera. Używanie klas LINQ to SQL w obrębie kontrolera 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 łatwą zmianę technologii dostępu do bazy danych w przyszłości i umożliwia łatwe testowanie klas kontrolerów.