пятница, 8 июля 2011 г.

MVC - часть3. CRUD логика (List)

В прошлой статье мы остановились на том, что создали Entity Framework модель по нашей БД. Давайте немного усложним нашу БД, чтоб было интереснее и немного сложнее. Допустим, будем на карте отображать объекты, полезные автомобилисту – автосервисы и автозаправочные станции (АЗС). Создадим таблицы для хранения наших данных (листинг 1).
Листинг 1 – Таблицы с данными об объектах карты
CREATE TABLE [dbo].[Map] (
  [MapObj_id] bigint IDENTITY(1, 1) NOT NULL,
  [ObjName] nvarchar(512) COLLATE Cyrillic_General_CI_AS NULL,
  [ObjAddress] nvarchar(512) COLLATE Cyrillic_General_CI_AS NULL,
  [ObjType] int NULL,
  [Description] nvarchar(max) COLLATE Cyrillic_General_CI_AS NULL,
  [Contact] nvarchar(max) COLLATE Cyrillic_General_CI_AS NULL,
  [Longitude] nvarchar(32) COLLATE Cyrillic_General_CI_AS NULL,
  [Latitude] nvarchar(32) COLLATE Cyrillic_General_CI_AS NULL,
  CONSTRAINT [CLIDX_Map_id] PRIMARY KEY CLUSTERED ([MapObj_id])
)

CREATE TABLE [dbo].[Comments] (
  [Comm_id] bigint IDENTITY(1, 1) NOT NULL,
  [MapObj_id] bigint NOT NULL,
  [CommentText] nvarchar(4000) COLLATE Cyrillic_General_CI_AS
CONSTRAINT [NNULL_Comments_Comment] DEFAULT '' NOT NULL,
  [Rating] int NOT NULL,
  [Author] nvarchar(32) COLLATE Cyrillic_General_CI_AS
CONSTRAINT [NNULL_Comment_Author] DEFAULT 'неизвестный' NOT NULL,
  CONSTRAINT [CLIDX_Comment_id] PRIMARY KEY CLUSTERED ([Comm_id]),
  CONSTRAINT [CK_Comment_Rating] CHECK ([Rating]<(11) AND [Rating]>(0)),
  CONSTRAINT [FK_Comments_MapObjId] FOREIGN KEY ([MapObj_id])
  REFERENCES [dbo].[Map] ([MapObj_id])
  ON UPDATE CASCADE
  ON DELETE CASCADE
)
Разберемся. Таблица Map – это данные об объектах карты: название, адрес, контакты, координаты, тип объекта (1 – автосервис, 2 - азс). Таблица Comments – это комментарии, которые оставляют пользователи о каких-либо объектах, содержит сам текст комментария, автора, оценку пользователя. Таблица Map связана с Comments внешним ключом отношением 1 ко многим (рисунок 1), т.е. у одного объекта может быть куча комментариев. Ну, это и понятно.
Рисунок 1 – Сущности из нашей БД

Кроме того, есть ограничение на оценку (может быть только от 0 до 10) и другие мелочи – разберетесь.
Идем в раздел Models нашего проекта и удаляем нашу модель MapDataModel. Боятся нечего, мы же помним, что архитектура MVC сильна разделением ответственности и все такое – вот мы сейчас на место удаленной модели создадим новую, остальной проект даже не заметит. Но перед этим еще один момент – в прошлой статье мы сгенерировали класс для работы с нашими данными, который назвался ProjectEntities. Чтоб все легло гладко, идем в файл Web.config, ищем там секцию connectionStrings, а в ней - наш ProjectEntities. Удаляем эту строку и со спокойной душой повторяем все шаги из прошлой статьи для нашей новой БД.
Осталось поправить в методе GetListObjectMap() нашего DataManager'а названия полей нашей обновленной таблицы.
Теперь все готово для дальнейших манипуляций.
Итак, что такое CRUD? Само слово - аббревиатура от слов Create, Read, Update, Delete. Т.е. это базовые операции управления данными. Применительно к нашему проекту программирование CRUD – логики – это создание (генерация) представлений, которые бы обеспечивали бы эти самые операции. Немного непонятно, но мы разберемся.
Давайте для начала сделаем самое простое – отобразим наши объекты карты в виде некой таблицы - списка, т.е. мы выполним операцию Read.
Для начала, научим наш DataManager формировать список объектов карты. Для этого создадим метод как в листинге 2.
Листинг 2 – Получение списка объектов карты
        public IQueryable<Map> GetMapObjets()
        {
            return _db.Map;
        }
В общем, все понятно – получаем список объектов.
Идем теперь в наш контроллер и добавляем экшен как в листинге 3.
Листинг 3 – Экшен для отображения списка объектов карты
        [HttpGet]
        public ActionResult MapObject_List()
        {
            DataManager db = new DataManager();
           
            return View(db.GetMapObjets());

        }
Тут мы создаем список объектов и отдаем их странице, реализуем экшен только с атрибутом [HttpGet], т.е. только для запроса содержимого страницы (для отправки пользовательских данных используется атрибут [HttpPost]).  После этого щелкаем правой кнопкой на нашем новом экшене и выбираем в появившемся меню Add View, появится диалог как на рисунке 2.
Рисунок 2 – Диалог создания представления

В этом диалоге выбираем опцию Create a strongly-typed view (создать типизированное представление), это позволит нашему представлению работать с какой-либо из наших моделей. Далее в списке классов моделей выберем Map (MvcApplication3.Models), т.е. наше представление будет работать с моделью объекта карты. И, самое для нас интереное, выбираем в списке Scaffold template шаблон List, т.е. просто список объектов. Не забудем указать мастер пейдж. Результат на рисунке 3.
Рисунок 3 – Настройки представления списка объектов
Представление создали. Содержимое пока изучать не будем. Нам надо создать ссылку на это представление, поэтому идем в файл _Layout.cshtml и создаем там ссылку. Запускаем. Видим прекрасное (рисунок 4).
Рисунок 4 – Список наших объектов

Отлично!
Если попробовать пройтись по ссылкам Edit, Details, Delete, то выскочит ошибка. Почему? Правильно - потому, что у нас не реализованы соответствующие экшены и представления. Попробуем сделать это в следующих статьях.
Удачи!

3 комментария:

Сергей комментирует...

Здравствуйте. Мне еще интересно, как делать поиск с выдачей результатом в виде списка (как на рис.4). насколько я понимаю это нужно делать в контроллере?

dedMazDie комментирует...

Добрый день!
Мне не до конца понятно, как вы хотите поиск организовать. Я делал в одном проекте окошко для ввода поисковой строки и список, куда валятся найденные объекты. При клике на элементе списка карта показывала данный объект. Но это все было целиком сделано на js с использованием Яндекс API. Как это делать в проекте на MVC даже не знаю еще. Но в ToDo-листе поиск стоит, так что делать буду по любому :)

Сергей комментирует...

Я хочу сделать так: область для поиска с выбором нескольких критериев. При нажатии Искать выполняется поиск и результатом является список найденных объектов. Вот и думаю что в контроллере нужно сделать метод который ищет и возвращает выборку. Показывать аналогично стандартному List. Но как, пока тоже не знаю.