Создание классов модели в LINQ to SQL (VB)

от Корпорации Майкрософт

Загрузить PDF-файл

Цель этого руководства — объяснить один из методов создания классов моделей для ASP.NET приложения MVC. В этом руководстве описано, как создавать классы моделей и осуществлять доступ к базе данных, используя преимущества Microsoft LINQ to SQL.

Цель этого руководства — объяснить один из методов создания классов моделей для ASP.NET приложения MVC. В этом руководстве описано, как создавать классы моделей и осуществлять доступ к базе данных, используя преимущества Microsoft LINQ to SQL.

В этом руководстве мы создадим базовое приложение базы данных Movie. Мы начнем с создания приложения базы данных Movie самым быстрым и простым способом. Мы выполняем весь доступ к данным непосредственно из действий контроллера.

Далее вы узнаете, как использовать шаблон репозитория. Использование шаблона репозитория требует немного дополнительных трудоемких трудоемких работ. Однако преимущество внедрения этого шаблона заключается в том, что он позволяет создавать приложения, которые можно адаптировать к изменениям и которые можно легко тестировать.

Что такое класс модели?

Модель MVC содержит всю логику приложения, которая не содержится в представлении MVC или контроллере MVC. В частности, модель MVC содержит всю бизнес-логику приложения и логику доступа к данным.

Для реализации логики доступа к данным можно использовать различные технологии. Например, можно создавать классы доступа к данным с помощью классов Microsoft Entity Framework, NHibernate, Subsonic или ADO.NET.

В этом руководстве используется LINQ to SQL для запроса и обновления базы данных. LINQ to SQL предоставляет очень простой способ взаимодействия с базой данных Microsoft SQL Server. Однако важно понимать, что платформа MVC ASP.NET никак не привязана к LINQ to SQL. ASP.NET MVC совместим с любой технологией доступа к данным.

Создание базы данных фильмов

В этом руководстве мы создадим простое приложение базы данных Movie, чтобы проиллюстрировать, как можно создавать классы моделей. Первым шагом является создание новой базы данных. Щелкните правой кнопкой мыши папку App_Data в окне Обозреватель решений и выберите пункт меню Добавить, Создать элемент. Выберите шаблон базы данных SQL Server, присвойте ему имя MoviesDB.mdf и нажмите кнопку Добавить (см. рис. 1).

Добавление новой базы данных SQL Server

Рис. 01. Добавление новой базы данных SQL Server (щелкните для просмотра полноразмерного изображения)

После создания базы данных ее можно открыть, дважды щелкнув файл MoviesDB.mdf в папке App_Data. Если дважды щелкнуть файл MoviesDB.mdf, откроется окно Серверная Обозреватель (см. рис. 2).

Окно Обозреватель сервера называется окном Обозреватель базы данных при использовании Visual Web Developer.

Снимок экрана: окно Обозреватель сервера, в котором показано, что папка Tables выделена в иерархии папок.

Рис. 02. Использование окна Обозреватель сервера (щелкните для просмотра полноразмерного изображения)

Нам нужно добавить в базу данных одну таблицу, которая представляет наши фильмы. Щелкните правой кнопкой мыши папку Таблицы и выберите пункт меню Добавить новую таблицу. При выборе этого пункта меню откроется Designer таблица (см. рис. 3).

Снимок экрана: окно Microsoft Visual Studio с функцией Designer таблицы.

Рис. 03. Designer таблицы (щелкните для просмотра полноразмерного изображения)

В таблицу базы данных необходимо добавить следующие столбцы:

Имя столбца Тип данных Разрешить значения NULL
Идентификатор Int Неверно
Заголовок Nvarchar(200) Неверно
Директор Nvarchar(50) Неверно

Для столбца Id необходимо выполнить две особые действия. Сначала необходимо пометить столбец Id как столбец первичного ключа, выбрав столбец в Designer таблицы и щелкнув значок ключа. LINQ to SQL требует указывать столбцы первичного ключа при вставке или обновлении базы данных.

Затем необходимо пометить столбец Id как столбец Identity, назначив значение Да свойству Is Identity (см. рис. 3). Столбец Identity — это столбец, которому присваивается новый номер автоматически при добавлении новой строки данных в таблицу.

После внесения этих изменений сохраните таблицу с именем tblMovie. Вы можете сохранить таблицу, нажав кнопку Сохранить.

Создание классов LINQ to SQL

Наша модель MVC будет содержать LINQ to SQL классов, представляющих таблицу базы данных tblMovie. Самый простой способ создать эти LINQ to SQL классы — щелкнуть правой кнопкой мыши папку Models, выбрать Добавить, Создать элемент, выбрать шаблон Классы LINQ to SQL, присвоить классам имя Movie.dbml и нажать кнопку Добавить (см. рис. 4).

Создание классов LINQ to SQL

Рис. 04. Создание классов LINQ to SQL (щелкните для просмотра полноразмерного изображения)

Сразу после создания классов LINQ to SQL movie появится реляционный конструктор объектов. Таблицы базы данных можно перетащить из окна Серверная Обозреватель на реляционный конструктор объектов, чтобы создать классы LINQ to SQL, представляющие определенные таблицы базы данных. Необходимо добавить таблицу базы данных tblMovie в реляционный конструктор объектов (см. рис. 4).

Использование реляционный конструктор объектов

Рис. 05. Использование реляционный конструктор объектов (щелкните для просмотра полноразмерного изображения)

По умолчанию реляционный конструктор объектов создает класс с тем же именем, что и таблица базы данных, которую вы перетаскиваете в Designer. Однако мы не хотим называть наш класс tblMovie. Поэтому щелкните имя класса в Designer и измените имя класса на Movie.

Наконец, не забудьте нажать кнопку Сохранить (изображение на дискете), чтобы сохранить классы LINQ to SQL. В противном случае классы LINQ to SQL не будут созданы реляционный конструктор объектов.

Использование LINQ to SQL в действии контроллера

Теперь, когда у нас есть LINQ to SQL классов, мы можем использовать эти классы для получения данных из базы данных. В этом разделе описано, как использовать классы LINQ to SQL непосредственно в действии контроллера. Мы отобразим список фильмов из таблицы базы данных tblMovies в представлении MVC.

Сначала необходимо изменить класс HomeController. Этот класс можно найти в папке Контроллеры приложения. Измените класс так, чтобы он выглядел как класс в листинге 1.

Листинг 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

Действие Index() в листинге 1 использует класс LINQ to SQL DataContext (MovieDataContext) для представления базы данных MoviesDB. Класс MoveDataContext был создан реляционный конструктор объектов Visual Studio.

Запрос LINQ выполняется к DataContext, чтобы получить все фильмы из таблицы базы данных tblMovies. Список фильмов назначается локальной переменной с именем movies. Наконец, список фильмов передается в представление с помощью данных представления.

Чтобы показать фильмы, необходимо изменить представление Индекс. Представление Индекс можно найти в папке Views\Home\. Обновите представление Индекс, чтобы оно выглядело как представление в листинге 2.

Листинг 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>

Обратите внимание, что измененное представление индексов содержит директиву <%@ импорта пространства имен %> в верхней части представления. Эта директива импортирует пространство имен MvcApplication1. Это пространство имен требуется для работы с классами моделей, в частности с классом Movie, в представлении.

Представление в листинге 2 содержит цикл For Each, который выполняет итерацию по всем элементам, представленным свойством ViewData.Model. Значение свойства Title отображается для каждого фильма.

Обратите внимание, что значение свойства ViewData.Model приводится к IEnumerable. Это необходимо для циклического просмотра содержимого ViewData.Model. Другой вариант — создать строго типизированное представление. При создании строго типизированного представления свойство ViewData.Model приводится к определенному типу в классе кода программной части представления.

Если вы запустите приложение после изменения класса HomeController и представления индекса, вы получите пустую страницу. Вы получите пустую страницу, так как в таблице базы данных tblMovies нет записей фильмов.

Чтобы добавить записи в таблицу базы данных tblMovies, щелкните правой кнопкой мыши таблицу базы данных tblMovies в окне Обозреватель сервера (окно Обозреватель базы данных в Visual Web Developer) и выберите пункт меню Показать данные таблицы. Записи фильмов можно вставить с помощью появиющейся сетки (см. рис. 5).

Вставка фильмов

Рис. 06. Вставка фильмов (щелкните для просмотра полноразмерного изображения)

После добавления записей базы данных в таблицу tblMovies и запуска приложения вы увидите страницу на рис. 7. Все записи базы данных фильмов отображаются в маркированных списках.

Отображение фильмов в представлении индекса

Рис. 07. Отображение фильмов в представлении индекса (щелкните, чтобы просмотреть полноразмерное изображение)

Использование шаблона репозитория

В предыдущем разделе мы использовали LINQ to SQL классов непосредственно в действии контроллера. Мы использовали класс MovieDataContext непосредственно из действия контроллера Index(). Нет ничего плохого в этом в случае простого приложения. Однако работа непосредственно с LINQ to SQL в классе контроллера создает проблемы при создании более сложного приложения.

Использование LINQ to SQL в классе контроллера затрудняет переключение технологий доступа к данным в будущем. Например, вы можете перейти с использования Microsoft LINQ to SQL на Microsoft Entity Framework в качестве технологии доступа к данным. В этом случае потребуется переписать каждый контроллер, который обращается к базе данных в приложении.

Использование LINQ to SQL в классе контроллера также усложняет создание модульных тестов для приложения. Как правило, вы не хотите взаимодействовать с базой данных при выполнении модульных тестов. Вы хотите использовать модульные тесты для тестирования логики приложения, а не сервера базы данных.

Чтобы создать приложение MVC, которое более адаптируется к будущим изменениям и может быть проще тестировать, следует рассмотреть возможность использования шаблона репозитория. При использовании шаблона репозитория создается отдельный класс репозитория, содержащий всю логику доступа к базе данных.

При создании класса репозитория создается интерфейс, представляющий все методы, используемые классом репозитория. В контроллерах вы пишете код в интерфейсе , а не в репозитории. Таким образом, в будущем вы сможете реализовать репозиторий с помощью различных технологий доступа к данным.

Интерфейс в листинге 3 называется IMovieRepository и представляет один метод с именем ListAll().

Листинг 3. Models\IMovieRepository.vb

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

Класс репозитория в листинге 4 реализует интерфейс IMovieRepository. Обратите внимание, что он содержит метод с именем ListAll(), соответствующий методу, необходимому для интерфейса IMovieRepository.

Листинг 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

Наконец, класс MoviesController в листинге 5 использует шаблон Репозиторий. Она больше не использует LINQ to SQL классы напрямую.

Листинг 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
}

Обратите внимание, что класс MoviesController в листинге 5 содержит два конструктора. Первый конструктор, конструктор без параметров, вызывается при запуске приложения. Этот конструктор создает экземпляр класса MovieRepository и передает его во второй конструктор.

Второй конструктор имеет один параметр: параметр IMovieRepository. Этот конструктор просто присваивает значение параметра полю уровня класса с именем _repository.

Класс MoviesController использует шаблон проектирования программного обеспечения, называемый шаблоном внедрения зависимостей. В частности, используется так называемый внедрение зависимостей конструктора. Дополнительные сведения об этом шаблоне см. в следующей статье Мартина Фаулера:

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

Обратите внимание, что весь код в классе MoviesController (за исключением первого конструктора) взаимодействует с интерфейсом IMovieRepository, а не с фактическим классом MovieRepository. Код взаимодействует с абстрактным интерфейсом, а не с конкретной реализацией интерфейса.

Если вы хотите изменить технологию доступа к данным, используемую приложением, можно просто реализовать интерфейс IMovieRepository с классом, использующим альтернативную технологию доступа к базе данных. Например, можно создать класс EntityFrameworkMovieRepository или SubSonicMovieRepository. Так как класс контроллера запрограммирован на интерфейс, можно передать новую реализацию IMovieRepository в класс контроллера, и класс продолжит работать.

Кроме того, если вы хотите протестировать класс MoviesController, можно передать класс репозитория поддельных фильмов в MoviesController. Класс IMovieRepository можно реализовать с помощью класса, который фактически не обращается к базе данных, но содержит все необходимые методы интерфейса IMovieRepository. Таким образом, можно выполнить модульное тестирование класса MoviesController без фактического доступа к реальной базе данных.

Итоги

Цель этого руководства состояла в том, чтобы продемонстрировать, как можно создавать классы моделей MVC, используя преимущества Microsoft LINQ to SQL. Мы изучили две стратегии отображения данных базы данных в ASP.NET приложении MVC. Сначала мы создали LINQ to SQL классы и использовали их непосредственно в действии контроллера. Использование LINQ to SQL классов в контроллере позволяет быстро и легко отображать данные базы данных в приложении MVC.

Далее мы изучили немного более сложный, но, безусловно, более эффективный способ отображения данных базы данных. Мы воспользовались шаблоном репозитория и поместили всю логику доступа к базе данных в отдельный класс репозитория. В нашем контроллере мы написали весь код для интерфейса, а не для конкретного класса. Преимущество шаблона репозитория заключается в том, что он позволяет легко изменять технологии доступа к базам данных в будущем и позволяет легко тестировать классы контроллеров.