Поделиться через


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

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

Загрузить 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 — это столбец, которому присваивается новый номер автоматически при добавлении новой строки данных в таблицу.

Создание классов 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 в реляционный конструктор объектов (см. рис. 5).

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

Рис. 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.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);
          }
     }
}

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

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

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

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

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

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

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

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

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

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

Рис. 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.cs

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

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

Листинг 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 5 использует шаблон репозитория. Она больше не использует LINQ to SQL классы напрямую.

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

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

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

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

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

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

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

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

Итоги

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

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