Онлайн-дневник студента

  • Вид работы:
    Дипломная (ВКР)
  • Предмет:
    Информационное обеспечение, программирование
  • Язык:
    Русский
    ,
    Формат файла:
    MS Word
    1,6 Мб
  • Опубликовано:
    2017-06-16
Вы можете узнать стоимость помощи в написании студенческой работы.
Помощь в написании работы, которую точно примут!

Онлайн-дневник студента

Оглавление

Введение

1. Обзор технологий

1.1 Обзор технологий создания веб-приложений

PHP

Ruby On Rails

Python

Вывод

2.2 Обзор СУБД

MySQL

PostgreSQL

Microsoft SQL Server

MongoDB

3. Используемые технологии серверной части веб-приложения

3.1 3-х уровневая серверная архитектура

3.2 ASP.net MVC 5

3.3 С#

3.4 LINQ

3.5 ASP.net Identity

3.6 Entity Framework

3.7 Visual Studio 2015

3.8 MS SQL Server

3.9 IIS

4. Описание работы приложения

4.1 Инфологическая модель базы данных

Пояснение к ER-диаграмме

4.3 Физическая модель данных

4.4 Скрипты создания таблиц

4.5 Используемые SQL запросы

4.6 Описание сценария приложения

Общее описание

Реализация сценария преподавателя

Основная страница для преподавателя где выводятся оценки для выбранной группы по выбранной дисциплине

Выбор преподавателем тех групп и предметов по которым он выставляет оценки

Архив где выводятся проставленные оценки за прошлые семестры

Создание таблицы - журнал

Студент

Основнная страница для студента с просмотром своих оценок

Подача заявки на регистрацию студентом

Администратор

Основная типовая страница для Группы

Создание Группы

Редактирование Группы

Удаление Группы

Принятие заявки на регистрацию студента

5. Тестирование

6. Руководство пользователя

6.2 Преподаватель

Общее руководство для преподавателя

6.3 Администратор

Поиск

Создание

Редактирование

Удаление

Приём заявок на регистрацию студента

Журнал

Общее руководство для администратора

7. Руководство по установке и сопровождению ПО

Программные требования

Хранение данных

Публикация на веб-сервере IIS

8. Заключение

Список используемых источников

Введение


В этой дипломной работе разрабатывается онлайн дневник студента, в частности его серверная часть. Это веб-приложение, потенциально, будет использоваться в СПбГМТУ.

Интернет и цифровые технологии все увереннее становятся неотъемлемой частью всех сфер жизнедеятельности современного человека. Не стала исключением и система образования, в которой электронные учебники постепенно вытесняют обычные книги, а ноутбуки и планшеты - традиционные тетради. По современным требованиям успеваемость студентов также должна хранится в цифровом виде.

Онлайн дневник несёт в себе некоторые преимущества по сравнению с обычным дневником. Первое это доступ к нему в любое время и в любом месте, если есть доступ в интернет с того или иного устройства. Второе, это автоматическая аналитика успеваемости студентов.

1. Обзор технологий


1.1 Обзор технологий создания веб-приложений


PHP

PHP был создан в 1994 году датским программистом РасмусомЛердорфом и изначально представлял собой набор скриптов на другом языке Perl. Позже этот набор скриптов был переписан в интерпретатор на языке Си. И с самого возникновения PHP (сокращение от PHP: Hypertext Preprocessor - PHP: Препроцессор гипертекста) представлял удобный набор инструментов для упрощенного создания веб-сайтов и веб-приложений.

На сегодняшний день PHP является наиболее распространенным языком веб-программирования. Подавляющие большинство сайтов и веб-сервисов в интернете написано с помощью PHP. По некоторым оценкам PHP применяется более чем на 80% сайтов, среди которых такие сервисы, как facebook.com, vk.com, baidu.com и другие. И такая популярность неудивительна. Простота языка позволяет быстро и легко создавать сайты и порталы различной сложности.

Ruby On Rails

Это полноценный, многоуровневый фреймворк на Ruby для построения веб-приложений, использующих базы данных, который основан на архитектуре Модель-Представление-Контроллер (Model-View-Controller, MVC). Динамичный AJAX-интерфейс, обработка запросов и выдача данных в контроллерах, предметная область, отраженная в базе данных, - для всего этого Rails предоставляет однородную среду разработки на Ruby. Все, что необходимо для начала - база данных и веб-сервер.

Python

Универсальный язык программирования, применимый в том числе и в вебе. С технической точки зрения web-приложение на Python - полноценное приложение, загруженное в память, обладающее своим внутренним состоянием, сохраняемым от запроса к запросу.

В контексте веб-разработки в первую очередь стоит упомянуть фреймворк Django.

Django - это высокоуровневый питоновский Web-фреймворк, который реализован на основе архитектуры MVC. Django имеет прозрачный дизайн, дает возможность для оперативной разработки Web-приложений, позволяет разрабатывать динамические Web-сайты.

Отличительные особенности Django:

любой запрос обрабатывается программно и перенаправляется на свой адрес (url);

разделение контента и представления с помощью шаблонов;

абстрагирование от низкого уровня баз данных.

Вывод

Лидирующей технологией в веб-программирование серверной части является - PHP. Для него существует множество конкурирующих фреймворков и он обладает самым большим комьюнити.

Объединяющей деталью большинства современных фреймворков является использование паттерна MVC.

Выбор пал на ASP.net потому что:

есть опыт использования С#.

Visual Studio - удобное IDE для Windows.

ASP.net MVC (теперь ASP.net Core) - активно развивающиеся технология.

2.2 Обзор СУБД


СУБД - Система управления базами данных представляет собой совокупность языковых и программных средств, которые обеспечивают управление созданием и использованием баз данных.

MySQL

Свободная реляционная система управления базами данных. Разработку и поддержку MySQL осуществляет корпорация Oracle, получившая права на торговую марку вместе с поглощённой Sun Microsystems, которая ранее приобрела шведскую компанию MySQL AB. Продукт распространяется как под GNU General Public License, так и под собственной коммерческой лицензией. Помимо этого, разработчики создают функциональность по заказу лицензионных пользователей. Именно благодаря такому заказу почти в самых ранних версиях появился механизм репликации.

MySQL является решением для малых и средних приложений. Входит в состав серверов WAMP, AppServ, LAMP и в портативные сборки серверов Денвер, XAMPP, VertrigoServ. Обычно MySQL используется в качестве сервера, к которому обращаются локальные или удалённые клиенты, однако в дистрибутив входит библиотека внутреннего сервера, позволяющая включать MySQL в автономные программы.

Гибкость СУБД MySQL обеспечивается поддержкой большого количества типов таблиц: пользователи могут выбрать как таблицы типа MyISAM, поддерживающие полнотекстовый поиск, так и таблицы InnoDB, поддерживающие транзакции на уровне отдельных записей. Более того, СУБД MySQL поставляется со специальным типом таблиц EXAMPLE, демонстрирующим принципы создания новых типов таблиц. Благодаря открытой архитектуре и GPL-лицензированию, в СУБД MySQL постоянно появляются новые типы таблиц.

MySQL возникла как попытка применить mSQL к собственным разработкам компании: таблицам, для которых использовались ISAM - подпрограммы низкого уровня. В результате был выработан новый SQL-интерфейс, но API-интерфейс остался в наследство от mSQL. Откуда происходит название "MySQL" - доподлинно неизвестно. Разработчики дают два варианта: либо потому, что практически все наработки компании начинались с префикса My, либо в честь девочки по имени My, дочери Майкла Монти Видениуса, одного из разработчиков системы.

Логотип MySQL в виде дельфина носит имя "Sakila". Он был выбран из большого списка предложенных пользователями "имён дельфина". Имя "Sakila" было отправлено Open Source-разработчиком Ambrose Twebaze.

PostgreSQL

Это объектно-реляционная система управления базами данных с открытым исходным кодом.

PostgreSQL создана на основе некоммерческой СУБД Postgres, разработанной как open-source проект в Калифорнийском университете в Беркли. К разработке Postgres, начавшейся в 1986 году, имел непосредственное отношение Майкл Стоунбрейкер, руководитель более раннего проекта Ingres, на тот момент уже приобретённого компанией Computer Associates. Название расшифровывалось как "Post Ingres", и при создании Postgres были применены многие уже ранее сделанные наработки.

Стоунбрейкер и его студенты разрабатывали новую СУБД в течение восьми лет с 1986 по 1994 год. За этот период в синтаксис были введены процедуры, правила, пользовательские типы и другие компоненты. В 1995 году разработка снова разделилась: Стоунбрейкер использовал полученный опыт в создании коммерческой СУБД Illustra, продвигаемой его собственной одноимённой компанией (приобретённой впоследствии компанией Informix), а его студенты разработали новую версию Postgres - Postgres95, в которой язык запросов POSTQUEL - наследие Ingres - был заменен на SQL.

Разработка Postgres95 была выведена за пределы университета и передана команде энтузиастов. Новая СУБД получила имя, под которым она известна и развивается в текущий момент - PostgreSQL.

Microsoft SQL Server

Система управления реляционными базами данных, разработанная корпорацией Microsoft. Основной используемый язык запросов - Transact-SQL, создан совместно Microsoft и Sybase. Transact-SQL является реализацией стандарта ANSI/ISO по структурированному языку запросов (SQL) с расширениями. Используется для работы с базами данных размером от персональных до крупных баз данных масштаба предприятия; конкурирует с другими СУБД в этом сегменте рынка.

СУБД является частью длинной цепочки специализированного программного обеспечения, которое корпорация Microsoft создала для разработчиков. А это значит, что все звенья этой цепи (приложения) глубоко интегрированы между собой.

То есть их инструментарий легко взаимодействует между собой, что во многом упрощает процесс разработки и написания программного кода. Примером такой взаимосвязи является среда программирования MS Visual Studio. В ее инсталляционный пакет уже входит SQL Server Express Edition.

Конечно, это не единственная популярная СУБД на мировом рынке. Но именно она является более приемлемой для компьютеров, работающих под управлением Windows, за счет своей направленности именно на эту операционную систему. И не только из-за этого.

Преимущества MS SQL Server:

Обладает высокой степенью производительности и отказоустойчивости;

Является многопользовательской СУБД и работает по принципу "клиент-сервер";

Тесная интеграция с операционной системой Windows;

Поддержка удаленных подключений;

Поддержка популярных типов данных, а также возможность создания триггеров и хранимых процедур;

Встроенная поддержка ролей пользователей;

Расширенная функция резервного копирования баз данных;

Высокая степень защищенности;

Каждый выпуск включает в себя несколько специализированных редакций.

MongoDB

Документоориентированная система управления базами данных (СУБД) с открытым исходным кодом, не требующая описания схемы таблиц. Классифицирована как NoSQL, использует JSON-подобные документы и схему базы данных. Написана на языке C++.

СУБД управляет наборами JSON-подобных документов, хранимых в двоичном виде в формате BSON. Хранение и поиск файлов в MongoDB происходит благодаря вызовам протокола GridFS. Подобно другим документоориентированным СУБД (CouchDB и др.), MongoDB не является реляционной СУБД. В СУБД:

Нет такого понятия, как "транзакция". Атомарность гарантируется только на уровне целого документа, то есть частичного обновления документа произойти не может.

Отсутствует понятие "изоляции". Любые данные, которые считываются одним клиентом, могут параллельно изменяться другим клиентом.

В MongoDB реализована асинхронная репликация в конфигурации "ведущий - ведомый" (англ. master - slave), основанная на передаче журнала изменений с ведущего узла на ведомые. Поддерживается автоматическое восстановление в случае выхода из строя ведущего узла. Серверы с запущенным процессом mongod должны образовать кворум, чтобы произошло автоматическое определение нового ведущего узла. Таким образом, если не используется специальный процесс-арбитр (процесс mongod, только участвующий в установке кворума, но не хранящий никаких данных), количество запущенных реплик должно быть нечётным.

цифровой дневник студент онлайн

3. Используемые технологии серверной части веб-приложения


3.1 3-х уровневая серверная архитектура


·        Слой клиент-интерфейс HTML5+CSS3+JS

·        Слой логики - ASP.net MVC 5

·        Слой данных - MS SQL Server

Нас интересует слой логики и слой данных.

3.2 ASP.net MVC 5


ASP.net MVC представляет собой платформу для создания сайтов и веб-приложений с использованием паттерна (или шаблона) MVC (model - view - controller).

Работа над новой платформой была начата в 2007 году, а в 2009 году появилась первая версия. В итоге к текущему моменту фреймворк обрел большую популярность по всему миру благодаря своей гибкости и адаптивности.

Шаблон MVC, лежащий в основе новой платформы, подразумевает взаимодействие трех компонентов: контроллера (controller), модели (model) и представления (view). Что же представляют эти компоненты?

Контроллер (controller) представляет класс, с которого собственно и начинается работа приложения. Этот класс обеспечивает связь между моделью и представлением. Получая вводимые пользователем данные, контроллер исходя из внутренней логики при необходимости обращается к модели и генерирует соответствующее представление.

Представление (view) - это собственно визуальная часть или пользовательский интерфейс приложения - например, html-страница, через которую пользователь, зашедший на сайт, взаимодействует с веб-приложением.

Модель (model) представляет набор классов, описывающих логику используемых данных.

3.3 С#


Упоминаю ASP.net MVC стоит рассказать о том языке программирования, для которого он написан.

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

По сравнению с другими языками C# достаточно молодой, но в то же время он уже прошел большой путь. Первая версия языка вышла вместе с релизом Microsoft Visual Studio.net в феврале 2002 года. Текущей версией языка является версия C# 7.0, которая вышла в 7 марта 2017 года вместе с Visual Studio 2017.

C# является языком с Си-подобным синтаксисом и близок в этом отношении к C++ и Java. Поэтому, если вы знакомы с одним из этих языков, то овладеть C# будет легче.

C# является объектно-ориентированным и в этом плане много перенял у Java и С++. Например, C# поддерживает полиморфизм, наследование, перегрузку операторов, статическую типизацию. Объектно-ориентированный подход позволяет решить задачи по построению крупных, но в тоже время гибких, масштабируемых и расширяемых приложений. И C# продолжает активно развиваться, и с каждой новой версией появляется все больше интересных функциональностей, как, например, лямбды, динамическое связывание, асинхронные методы и т.д.

3.4 LINQ


Важной частью платформы.net и языка C# в частности является LINQ. Он занимает важную часть в этом веб-приложении т.к. все запросы к БД написаны с помощью него. Теперь о самом LINQ.

LINQ (Language-Integrated Query) представляет простой и удобный язык запросов к источнику данных. В качестве источника данных может выступать объект, реализующий интерфейс IEnumerable (например, стандартные коллекции, массивы), набор данных DataSet, документ XML. Но вне зависимости от типа источника LINQ позволяет применить ко всем один и тот же подход для выборки данных.

3.5 ASP.net Identity


Это система аутентификации и авторизации на платформе.net. Можно обратить внимания в описании бд что у сущностей Студента и Преподавателя отсутствуют поля для логина и пароля, это потому что в данном веб-приложении для функционала аутентификации и авторизации используется Identity.

3.6 Entity Framework


Для доступа к бд в данном веб-приложении используется Entity Framework который представляет специальную объектно-ориентированную технологию на базе фреймворка.net для работы с данными. Если традиционные средства ADO.net позволяют создавать подключения, команды и прочие объекты для взаимодействия с базами данных, то Entity Framework представляет собой более высокий уровень абстракции, который позволяет абстрагироваться от самой базы данных и работать с данными независимо от типа хранилища. Если на физическом уровне мы оперируем таблицами, индексами, первичными и внешними ключами, но на концептуальном уровне, который нам предлагает Entity Framework, мы уже работает с объектами.

3.7 Visual Studio 2015


Это набор инструментов для создания программного обеспечения: от планирования до разработки пользовательского интерфейса, написания кода, тестирования, отладки, анализа качества кода и производительности, развертывания в средах клиентов и сбора данных телеметрии по использованию. Эти инструменты предназначены для максимально эффективной совместной работы; все они доступны в интегрированной среде разработки (IDE) Visual Studio. Visual Studio можно использовать для создания различных типов приложений, от простых приложений для магазина и игр для мобильных клиентов до больших и сложных систем, обслуживающих предприятия и центры обработки данных.

3.8 MS SQL Server


Microsoft SQL Server - система управления реляционными базами данных (СУБД), разработанная корпорацией Microsoft. Основной используемый язык запросов - Transact-SQL, создан совместно Microsoft и Sybase. Transact-SQL является реализацией стандарта ANSI/ISO по структурированному языку запросов (SQL) с расширениями. Используется для работы с небольшими и средними по размеру базами данных до крупных баз данных масштаба предприятия; конкурирует с другими СУБД в этом сегменте рынка.

3.9 IIS


Это проприетарный набор серверов для нескольких служб Интернета от компании Майкрософт. IIS распространяется с операционными системами семейства Windows NT.

Основным компонентом IIS является веб-сервер, который позволяет размещать в Интернете сайты. IIS поддерживает протоколы HTTP, HTTPS, FTP, POP3, SMTP, NNTP. По данным компании Netcraft на июнь 2015 года, почти 22 млн сайтов обслуживаются веб-сервером IIS, что составляет 12,32 % от общего числа веб-сайтов.

4. Описание работы приложения


4.1 Инфологическая модель базы данных


Модель представленна в виде ER-диграммы - это диграмма которая визуально описывает сущности предметной области их свойства и взаимосвязи.

ER-диаграмма модели базы данных:

Рис.1 Инфологическая модель базы данных

Пояснение к ER-диаграмме

Группа:

Номер группы храниться в своём первоначальном виде за первый курс т.е. вида“1120”, но не “1220”. Номер группы за тот или иной учебный вычисляется через поле “Год поступления”.

Академическая степень - имеется ввиду степени: бакалавриат, магистратура.

Форма обучения - имеется ввиду: очная и заочная форма обучения.

Таблица с оценками

Тип контроля знаний - имеются ввиду тот тип оценки знаний который будет проставляться в этой таблице. Пример: экзамен, зачёт, журнал, практика, курсовая работа.

Журнал - это оценки которые проставляет преподаватель в течении семестра (за тесты, работы и тп).

Семестр

Атрибуты “Начало семестра” и “Конец семестра” нужны для таблиц с оценками с типом контроля знаний - журнал. Что-бы по составить таблицу с оценками за весь семестр.

 

4.2 Даталогическая модель


Даталогическая модель отражает логические связи между элементами данных вне зависимости от их содержания и среды хранения.

Рис.2 Даталогическая модель базы данных

 

4.3 Физическая модель данных


Это модель данных которая описанна с помощью средств конкретной СУБД. В нашем случае это MS SQL Server 2016.

Рис.3 Физическая модель данных

Пояснение:

Добавлена таблица ApplicationsForRegistration. Она служит для того что бы студент подавал заявку на регистрацию.

4.4 Скрипты создания таблиц


Группа.

CREATE TABLE [dbo]. [Groups] (

[Id] INT IDENTITY (1, 1) NOT NULL,

[Number] INT NOT NULL,

[YearOfAdmission] INT NOT NULL,

[Faculty] NVARCHAR (128) NOT NULL,

[Degree] NVARCHAR (128) NOT NULL,

[FormOfStudy] NVARCHAR (128) NOT NULL,

[MonitorId] INT NULL,[PK_Groups] PRIMARY KEY CLUSTERED ([Id] ASC),[FK_dbo_Groups_dbo_Students_MonitorId] FOREIGN KEY ([MonitorId]) REFERENCES [dbo]. [Students] ([Id]) ON DELETE SET NULL

);NONCLUSTERED INDEX [IX_FK_dbo_Groups_dbo_Students_MonitorId][dbo]. [Groups] ([MonitorId] ASC); - Id старосты группы.

Внешний ключ на таблицу Student для старосты группы. При удалении этой таблицы Student то вместо неё ставиться null. Так как MonitorId не обязательное поле таблицы.

Используется некластеризованный индекс у внешнего ключа для увеличения скорости запросов.

Студент.TABLE [dbo]. [Students] (

[Id] INT IDENTITY (1, 1) NOT NULL,

[Number] NVARCHAR (128) NOT NULL,

[FullName] NVARCHAR (128) NOT NULL,

[YearOfBirth] INT NOT NULL,

[GroupId] INT NULL,

[Photo] VARBINARY (MAX) NULL,

[UserName] NVARCHAR (256) NULL,

[Email] NVARCHAR (128) NULL,[PK_Students] PRIMARY KEY CLUSTERED ([Id] ASC),[FK_dbo_Students_dbo_Groups_GroupId] FOREIGN KEY ([GroupId]) REFERENCES [dbo]. [Groups] ([Id]) ON DELETE SET NULL

);NONCLUSTERED INDEX [IX_FK_dbo_Students_dbo_Groups_GroupId][dbo]. [Students] ([GroupId] ASC);

Таблица Student ссылается на таблицу Group через поле GroupId, для того что бы студент был привязан ко одной из групп.

Поле UserName используется для того что связываться с аккаунтом (если он есть).

Используется некластеризованный индекс у внешнего ключа для увеличения скорости запросов.

Преподаватель.TABLE [dbo]. [Teachers] (

[Id] INT IDENTITY (1, 1) NOT NULL,

[FullName] NVARCHAR (128) NOT NULL,

[Departament] NVARCHAR (128) NOT NULL,

[UserName] NVARCHAR (128) NULL,[PK_Teachers] PRIMARY KEY CLUSTERED ([Id] ASC)

);

Поле UserName используется для того что связываться с аккаунтом (если он есть).

Дисциплина.TABLE [dbo]. [Subjects] (

[Id] INT IDENTITY (1, 1) NOT NULL,

[Name] NVARCHAR (128) NOT NULL,

[Departament] NVARCHAR (128) NOT NULL,[PK_Subjects] PRIMARY KEY CLUSTERED ([Id] ASC)

);

Семестр.TABLE [dbo]. [Semester] (

[Id] INT IDENTITY (1, 1) NOT NULL,

[BeginningDate] DATE NOT NULL,

[EndDate] DATE NOT NULL,

[Number] NVARCHAR (128) NOT NULL,

[Year] NVARCHAR (128) NOT NULL,KEY CLUSTERED ([Id] ASC)

);

Таблица с оценками.

CREATE TABLE [dbo]. [TableOfGrades] (

[Id] INT IDENTITY (1, 1) NOT NULL,

[TeachersGroupsSubjectId] INT NOT NULL,

[TypeOfKnowledgeControl] NVARCHAR (128) NOT NULL,

[SemesterId] INT NOT NULL,[PK_TableOfGrades] PRIMARY KEY CLUSTERED ([Id] ASC),[FK_dbo_TableOfGrades_dbo_TeachersGroupsSubjects_TeachersGroupsSubjectId] FOREIGN KEY ([TeachersGroupsSubjectId]) REFERENCES [dbo]. [TeachersGroupsSubjects] ([Id]) ON DELETE CASCADE,[FK_dbo_TableOfGrades_dbo_Semester_SemesterId] FOREIGN KEY ([SemesterId]) REFERENCES [dbo]. [Semester] ([Id])

);

Таблица с оценками имеет внешний на таблицу ПреподавательГруппаДисциплина, для того что бы однозначно связать оценки с преподавателем, группой и дисциплиной.

Так же имеется внешний ключ на таблицу Семестр для того что бы связать оценки с определённым семестром.

При удалении связанной таблицы ПреподавательГруппаДисциплина, то Таблица оценок удаляется вслед за ней.

Таблицу Семестр нельзя удалить пока она связанна хотя бы с одной Таблица оценок.

Оценка.

TABLE [dbo]. [TableEntry] (

[Id] INT IDENTITY (1, 1) NOT NULL,

[StudentId] INT NOT NULL,

[Date] DATE NULL,

[TableOfGradeId] INT NOT NULL,

[Value] NVARCHAR (128) NULL,[PK_TableEntry] PRIMARY KEY CLUSTERED ([Id] ASC),[FK_dbo_TableEntry_dbo_Students_StudentId] FOREIGN KEY ([StudentId]) REFERENCES [dbo]. [Students] ([Id]) ON DELETE CASCADE,[FK_dbo_TableEntry_dbo_TableOfGrades_TableOfGradeId] FOREIGN KEY ([TableOfGradeId]) REFERENCES [dbo]. [TableOfGrades] ([Id]) ON DELETE CASCADE

);NONCLUSTERED INDEX [IX_FK_dbo_TableEntry_dbo_Students_StudentId][dbo]. [TableEntry] ([StudentId] ASC);NONCLUSTERED INDEX [IX_FK_dbo_TableEntry_dbo_TableOfGrades_TableOfGradeId][dbo]. [TableEntry] ([TableOfGradeId] ASC);

Оценка имеет внешний ключ на Студента, чтобы связать оценку с определённым студентом. Так же имеется внешний ключ на Таблица оценок, для того что бы связать оценки с абстрактными данными хранящимися в Таблица оценок, такими данными как: преподаватель, дисциплина, группа, семестр.

При удалении связанного Студента или Таблицы оценок сама Оценка удаляется вслед за ними.

Используется некластеризованный индекс у внешних ключей для увеличения скорости запросов.

Преподаватель Группа Дисциплина

CREATE TABLE [dbo]. [TeachersGroupsSubjects] (

[Id] INT IDENTITY (1, 1) NOT NULL,

[GroupId] INT NOT NULL,

[SubjectId] INT NOT NULL,

[TeacherId] INT NOT NULL,[PK_TeachersGroupsSubjects] PRIMARY KEY CLUSTERED ([Id] ASC),[FK_dbo_TeachersGroupsSubjects_dbo_Subjects_SubjectId] FOREIGN KEY ([SubjectId]) REFERENCES [dbo]. [Subjects] ([Id]),[FK_dbo_TeachersGroupsSubjects_dbo_Teachers_TeacherId] FOREIGN KEY ([TeacherId]) REFERENCES [dbo]. [Teachers] ([Id]),[FK_dbo_TeachersGroupsSubjects_dbo_Groups_GroupId] FOREIGN KEY ([GroupId]) REFERENCES [dbo]. [Groups] ([Id])

);NONCLUSTERED INDEX [IX_FK_dbo_TeachersGroupsSubjects_dbo_Groups_GroupId][dbo]. [TeachersGroupsSubjects] ([GroupId] ASC);NONCLUSTERED INDEX [IX_FK_dbo_TeachersGroupsSubjects_dbo_Subjects_SubjectId][dbo]. [TeachersGroupsSubjects] ([SubjectId] ASC);NONCLUSTERED INDEX [IX_FK_dbo_TeachersGroupsSubjects_dbo_Teachers_TeacherId][dbo]. [TeachersGroupsSubjects] ([TeacherId] ASC);

 

Преподаватель Группа Дисциплина имеет внешние ключи на Группу, Дисциплину и Преподавателя так-как смысл самой таблицы ПреподавательГруппаДисциплина для того что абстрагировать эту связь 3-х таблиц от Таблицы с оценками.

При удалении одной из связанных таблиц Преподаватель Группа Дисциплина тоже удаляется.


4.5 Используемые SQL запросы


Для запросов к субд в данном приложении используется расширения языка Linq, который сам формирует необходимый SQL запрос, поэтому в коде нету привычного SQL кода, но тем не менее можно посмотреть созданный SQL запрос. Только внутри них указываются параметры вида “@p__linq__1”.

Select запросы:

) Запрос для выборки Оценок для Таблицы оценок у преподавателя

SELECT

[Extent1]. [Id] AS [Id],

[Extent1]. [TableOfGradeId] AS [TableOfGradeId],

[Extent1]. [Date] AS [Date],

[Extent1]. [Value] AS [Value],

[Extent1]. [StudentId] AS [StudentId][dbo]. [TableEntry] AS [Extent1]JOIN [dbo]. [TableOfGrades] AS [Extent2] ON [Extent1]. [TableOfGradeId] = [Extent2]. [Id]JOIN [dbo]. [Semester] AS [Extent3] ON [Extent2]. [SemesterId] = [Extent3]. [Id]JOIN [dbo]. [TeachersGroupsSubjects] AS [Extent4] ON [Extent2]. [TeachersGroupsSubjectId] = [Extent4]. [Id]([Extent4]. [GroupId] = '1') AND ([Extent4]. [TeacherId] = '1') AND ([Extent4]. [SubjectId] = '1') AND ([Extent3]. [Number] = '2') AND ([Extent3]. [Year] = '2016|2017') AND ([Extent2]. [TypeOfKnowledgeControl] = 'Exam')

) Пример запроса для выборки Студентов для преподавателя что бы составлять таблицы с оценками.

SELECT

[Filter1]. [Id1] AS [Id](SELECT [Extent1]. [Id] AS [Id1], [Extent2]. [GroupId] AS [GroupId1], [Extent2]. [SubjectId] AS [SubjectId], [Extent2]. [TeacherId] AS [TeacherId], [Extent3]. [SemesterId] AS [SemesterId][dbo]. [Students] AS [Extent1]JOIN [dbo]. [TeachersGroupsSubjects] AS [Extent2] ON [Extent1]. [GroupId] = [Extent2]. [GroupId]JOIN [dbo]. [TableOfGrades] AS [Extent3] ON [Extent2]. [Id] = [Extent3]. [TeachersGroupsSubjectId]N'Journal' = [Extent3]. [TypeOfKnowledgeControl]) AS [Filter1]JOIN [dbo]. [Semester] AS [Extent4] ON [Filter1]. [SemesterId] = [Extent4]. [Id]([Filter1]. [TeacherId] = '1') AND ([Filter1]. [GroupId1] = '1') AND ([Filter1]. [SubjectId] = '1006') AND ([Extent4]. [Number] = '2') AND ([Extent4]. [Year] = '2016|2017')

3) Пример запроса для выборки Семестров у студента.

SELECT

[Extent1]. [Id] AS [Id],

[Extent1]. [BeginningDate] AS [BeginningDate],

[Extent1]. [EndDate] AS [EndDate],

[Extent1]. [Number] AS [Number],

[Extent1]. [Year] AS [Year][dbo]. [Semester] AS [Extent1]JOIN [dbo]. [TableOfGrades] AS [Extent2] ON [Extent1]. [Id] = [Extent2]. [SemesterId]JOIN [dbo]. [TeachersGroupsSubjects] AS [Extent3] ON [Extent2]. [TeachersGroupsSubjectId] = [Extent3]. [Id]JOIN [dbo]. [Students] AS [Extent4] ON [Extent3]. [GroupId] = [Extent4]. [GroupId][Extent4]. [Id] = '1'

) Пример запроса для выборки названия Дисциплин у студента.

SELECT

[Extent1]. [Id] AS [Id],

[Extent1]. [BeginningDate] AS [BeginningDate],

[Extent1]. [EndDate] AS [EndDate],

[Extent1]. [Number] AS [Number],

[Extent1]. [Year] AS [Year][dbo]. [Semester] AS [Extent1]JOIN [dbo]. [TableOfGrades] AS [Extent2] ON [Extent1]. [Id] = [Extent2]. [SemesterId]JOIN [dbo]. [TeachersGroupsSubjects] AS [Extent3] ON [Extent2]. [TeachersGroupsSubjectId] = [Extent3]. [Id]JOIN [dbo]. [Students] AS [Extent4] ON [Extent3]. [GroupId] = [Extent4]. [GroupId][Extent4]. [Id] = '1'

) Пример запроса для выборки Оценок у студента.

SELECT

[Extent1]. [Id] AS [Id],

[Extent1]. [Value] AS [Value],

[Extent1]. [Date] AS [Date],

[Extent1]. [TableOfGradeId] AS [TableOfGradeId],

[Extent1]. [StudentId] AS [StudentId][dbo]. [TableEntry] AS [Extent1]JOIN [dbo]. [TableOfGrades] AS [Extent2] ON [Extent1]. [TableOfGradeId] = [Extent2]. [Id]JOIN [dbo]. [Semester] AS [Extent3] ON [Extent2]. [SemesterId] = [Extent3]. [Id]JOIN [dbo]. [TeachersGroupsSubjects] AS [Extent4] ON [Extent2]. [TeachersGroupsSubjectId] = [Extent4]. [Id]([Extent1]. [StudentId] = @p__linq__0) AND ([Extent4]. [SubjectId] = @p__linq__1) AND ([Extent3]. [Number] = @p__linq__2) AND ([Extent3]. [Year] = @p__linq__3)

Запрос Insert

) Создание Студента.

[dbo]. [Students] ([Number], [FullName], [YearOfBirth], [GroupId], [Photo], [UserName], [Email]) ('12415641', 'Кириллов Анатолий Павлович', '1995', '12', NULL, NULL, 'maliva1995@yandex.ru')

SELECT [Id][dbo]. [Students]@@ROWCOUNT > 0 AND [Id] = scope_identity ()

) Создание Группы[dbo]. [Groups] ([Number], [YearOfAdmission], [Faculty], [Degree], [FormOfStudy], [MonitorId])('1190', '2014', '2', 'Бакалавриат', 'Очная', NULL)[Id][dbo]. [Groups]@@ROWCOUNT > 0 AND [Id] = scope_identity ()

Запрос Delete

) Удаление Группы

DELETE [dbo]. [Groups]

WHERE ([Id] = '13')

) Удаление Студента

DELETE [dbo]. [Students]([Id] = @0)

Запрос Update

) Обновление Группы

UPDATE [dbo]. [Groups][Number] = '1110', [YearOfAdmission] = '2012', [Faculty] = 'ФКиО', [Degree] = 'Бакалавриат', [FormOfStudy] = 'Очная', [MonitorId] = NULL ([Id] = '11')

) Обновление Студента

UPDATE [dbo]. [Groups][Number] = '1110', [YearOfAdmission] = '2012', [Faculty] = 'ФКиО', [Degree] = 'Бакалавриат', [FormOfStudy] = 'Очная', [MonitorId] = NULL ([Id] = '11')

) Обновление Оценки у преподавателя в таблице.

UPDATE [dbo]. [TableEntry][Value] = '5' ([Id] = '116')

 


4.6 Описание сценария приложения


Общее описание

У нас в приложение 3 вида пользователя: Студент, Администратор, Преподаватель. Для каждого из них функционал разительно отличается.

Преподаватель:

·        Просматривать и редактировать оценки.

·        Может выбирать у какой группы и какой предмет введёт, создавая соответствующую связь в бд.

·        Создавать необходимые ему таблицы с различным видом контроля знаний (журнал, экзамен, зачёт, курсовая работа, практика.

Студент:

·        Подавать заявку на регистрацию

·        Просматривать свои оценки.

Администратор:

·        Удалять/редактировать/создавать основные сущности: Студент, Группа, Преподаватель, Дисциплина, ПреподавательГруппаДисциплина, Семестр.

·        Принимать заявки на регистрацию студента.

·        Изменять оценки в таблицах с оценками.

·        Просматривать аналитическую информацию по успеваемости.

Реализация сценария преподавателя


Основная страница для преподавателя где выводятся оценки для выбранной группы по выбранной дисциплине


Рис. 4 Заглавная страница преподавателя

Исходный код:

[HttpGet]ActionResult Index (int? group, int? subject)

{userName = HttpContext. User. Identity. Name;lecturerId = db. Teachers. Where (p => p. UserName == userName). First (). Id;

var toDaySemester = Semester. Today ();

// Формирует список групп у которых преподаватель ввёл в данном семестре

var findGroups = (from p in db. Groupsb in db. TeachersGroupsSubjects on p. Id equals b. GroupIdc in db. TableOfGrades on b. Id equals c. TeachersGroupsSubjectIdd in db. Semester on c. SemesterId equals d. Idb. TeacherId == lecturerId && d. Number == toDaySemester. Number &&. Year == toDaySemester. Yearnew

{= p. Id,= p. Number,= p. YearOfAdmission,= p. Faculty,= p. Degree,= p. MonitorId

}). ToList ();<Groups> groups = new List<Groups> ();(var group1 in findGroups)

{(groups. Find (p => p. Id == group1. Id) == null). Add (new Groups

{= group1. Id,= group1. Number,= group1. YearOfAdmission,= group1. Faculty,= group1. Degree,= group1. MonitorId

});

}(var b in groups)

{. Number = b. GetGroupNumber (Semester. Today ());

}. OrderBy (p => p. Number);firstGroup;(group == null)= groups. FirstOrDefault (). Id;= group. Value;. Groups = new SelectList (groups, "Id", "Number", groups. First (p => p. Id == firstGroup));

// Формируем список дисплин по одной из групп для преподавателя

var subjects = (from p in db. Subjectsb in db. TeachersGroupsSubjects on p. Id equals b. SubjectIdf in db. Groups on b. GroupId equals f. Idc in db. TableOfGrades on b. Id equals c. TeachersGroupsSubjectIdd in db. Semester on c. SemesterId equals d. Idb. TeacherId == lecturerId && d. Number == toDaySemester. Number && d. Year == toDaySemester. Year && f. Id == firstGroupnew

{= p. Name,= p. Id

}). ToList ();= subjects. Distinct (). ToList ();. OrderBy (p => p. Name);(subject == null)= subjects. First (). Id;. Subject = new SelectList (subjects, "Id", "Name", subjects. First (p => p. Id == subject));viewModel = new LecturerViewModel ();toDaySemester1 = GetTodaySemester ();lecId = db. Teachers. Where (p => p. UserName == userName). First (). Id;. GetAllFinalGrades (db, firstGroup, lecId, subject. Value, toDaySemester1);

// Заполнения модели представления

// Получение название предметов для журнала

viewModel. GetNamesOfStudents (db, firstGroup, lecId, subject. Value, toDaySemester1);

// Получение данных для заполнения области таблицы с оценками

viewModel. GetStudentsGrades (db, firstGroup, lecId, subject. Value, toDaySemester1);

// Для строки с названиями месяцев

viewModel. GetMounthNames ();

// С количеством дней в месяцах для для colspan.

viewModel. GetDaysMounth ();

// Для отображение строки где день месяца + день недели.

viewModel. GetDaysSemester ();

// Для формирование таблиц с итоговыми оценками

viewModel. GetAllFinalGrades (db, firstGroup, lecId, subject. Value, toDaySemester1);. Subject = db. Subjects. Find (subject);. Group = db. Groups. Find (firstGroup);View (viewModel);

}

[HttpPost]ActionResult Index (LecturerViewModel viewModel, string action)

{db = new DiaryConnection ();. Database. Log = s => System. Diagnostics. Debug. WriteLine (s);

// action - параметр отправляемый из кнопки "сохранить". В зависимости от него обновляеться нужная часть модели.

if (action == "Journal")

{(int i = 0; i < viewModel. ListOfGrades. Count; i++)

{(int j = 0; j < viewModel. ListOfGrades [i]. Count; j++)

{

// Обновляем отправленные данные таблицы

var foundTableEntry = viewModel. ListOfGrades [i] [j];tableEntry = db. TableEntry. Where (p => p. Id == foundTableEntry. Id). First ();. Value = foundTableEntry. Value;

}

}

}(action == "PassFailTest")

{(var b in viewModel. PassFailTestGrades)

{

// Обновляем отправленные данные таблицыtableEntry = db. TableEntry. Where (p => p. Id == b. Id). First ();. Value = b. Value;

}

}(action == "PracticalWork")

{(var b in viewModel. PracticalWorkGrades)

{tableEntry = db. TableEntry. Where (p => p. Id == b. Id). First ();. Value = b. Value;

}

}(action == "CoursePaper")

{(var b in viewModel. CoursePaperGrades)

{tableEntry = db. TableEntry. Where (p => p. Id == b. Id). First ();. Value = b. Value;

}(action == "Exam")

{(var b in viewModel. ExamGrades)

{tableEntry = db. TableEntry. Where (p => p. Id == b. Id). First ();. Value = b. Value;

}

}. SaveChanges ();Redirect ("/Lecturer/Index" + "/" + viewModel. Group. Id + "/" + viewModel. Subject. Id);

}

Пояснение:

C помощью HTTP запроса GET к методу Index выводится начальное представление. А с помощью запроса POST происходит обновление страницы.

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

Поля в таблицах свободны для редактирования, только нужно нажать кнопку сохранить под необходимой таблицей, что вызовет метод POST который сохранит изменения и обновит страницу.

Основные методы по формирование таблиц вынесены в класс LecturerViewModel.

Выбор преподавателем тех групп и предметов по которым он выставляет оценки


Рис. 5 Создание связи ПреподавательГруппаПредмет

Исходный код:

[HttpGet]ActionResult SelectGroupAndSubject ()

{userName = HttpContext. User. Identity. Name;groups = db. Groups. ToList ();(var b in groups)

{. Number = b. GetGroupNumber (Semester. Today ());

}. Lecturer = db. Teachers. Where (p => p. UserName == userName). First ();. Groups = new SelectList (groups, "Id", "Number");. Subjects = new SelectList (db. Subjects. ToList (), "Id", "Name");. TGS = db. TeachersGroupsSubjects. Where (p => p. Teachers. UserName == userName). ToList ();View ();

}

[HttpPost]ActionResult SelectGroupAndSubject ([Bind (Include = "Id,GroupId,TeacherId,SubjectId")] TeachersGroupsSubjects lgs, string isNewSubject, string newSubjectName, string newSubjectDepartament)

{(isNewSubject == "true")

{(db. Subjects. Where (p => p. Name == newSubjectName && p. Departament == newSubjectDepartament). ToList (). Count == 0)

{. Subjects. Add (new Subjects { Name = newSubjectName, Departament = newSubjectDepartament });. SaveChanges ();

}. SubjectId = db. Subjects. Where (p => p. Name == newSubjectName && p. Departament == newSubjectDepartament). First (). Id;

}(ModelState. IsValid)

{. TeachersGroupsSubjects. Add (lgs);. SaveChanges ();Redirect ("/Lecturer/Index" + "/" + lgs. GroupId + "/" + lgs. SubjectId);

}userName = HttpContext. User. Identity. Name;lecId = db. Teachers. Where (p => p. UserName == userName). First (). Id;groups = db. Groups. ToList ();(var b in groups)

{. Number = b. GetGroupNumber (Semester. Today ());

}. Lecturer = lecId;. Groups = new SelectList (groups, "Id", "Number");. Subjects = new SelectList (db. Subjects. ToList (), "Id", "Name");View ();

}

Пояснение:

Создавая выбирая группу и предмет, преподаватель волен выбрать: взять ему существующий предмет или создать новый. Снизу страницы отображены уже созданные связи.

Архив где выводятся проставленные оценки за прошлые семестры

Исходный код:

public ActionResult Archive (int? group, int? subject, string year, string semesterNumber)

{userName = HttpContext. User. Identity. Name;lecturerId = db. Teachers. Where (p => p. UserName == userName). First (). Id;findSemesters = (from p in db. Semesterc in db. TableOfGrades on p. Id equals c. SemesterIdg in db. TeachersGroupsSubjects on c. TeachersGroupsSubjectId equals g. Idf in db. Teachers on g. TeacherId equals f. Idf. Id == lecturerIdnew

{= p. Id,= p. BeginningDate,= p. EndDate,= p. Number,= p. Year

}). Distinct ();<Semester> semesters = new List<Semester> ();(var item in findSemesters)

{. Add (new Semester { Id = item. Id, BeginningDate = item. BeginningDate, EndDate = item. EndDate, Number = item. Number, Year = item. Year });

}semester;(year == null || semesterNumber == null)= semesters. FirstOrDefault ();= db. Semester. FirstOrDefault (p => p. Year == year && p. Number == semesterNumber);findGroups = (from p in db. Groupsb in db. TeachersGroupsSubjects on p. Id equals b. GroupIdc in db. TableOfGrades on b. Id equals c. TeachersGroupsSubjectIdd in db. Semester on c. SemesterId equals d. Idb. TeacherId == lecturerId && d. Number == semester. Number &&. Year == semester. Yearnew

{= p. Id,= p. Number,= p. YearOfAdmission,= p. Faculty,= p. Degree,= p. MonitorId

}). ToList ();<Groups> groups = new List<Groups> ();(var group1 in findGroups)

{(groups. Find (p => p. Id == group1. Id) == null). Add (new Groups

{= group1. Id,= group1. Number,= group1. YearOfAdmission,= group1. Faculty,= group1. Degree,= group1. MonitorId

});

}(var b in groups)

{. Number = b. GetGroupNumber (Semester. Today ());

}. OrderBy (p => p. Number);(group == null)= db. Groups. First (). Id;firstGroup = groups. First ();subjects = (from p in db. Subjectsb in db. TeachersGroupsSubjects on p. Id equals b. SubjectIdf in db. Groups on b. GroupId equals f. Idc in db. TableOfGrades on b. Id equals c. TeachersGroupsSubjectIdd in db. Semester on c. SemesterId equals d. Idb. TeacherId == lecturerId && d. Number == semester. Number && d. Year == semester. Year && f. Id == firstGroup. Idnew

{= p. Name,= p. Id

}). ToList ();= subjects. Distinct (). ToList ();. OrderBy (p => p. Name);(subject == null)= db. Subjects. First (). Id;

// SelectList для симестров надо делать вручную. У меня на представление есть пример.

ViewBag. Semesters = semesters;. Groups = new SelectList (groups, "Id", "Number", groups. FirstOrDefault (p => p. Id == group));. Subjects = new SelectList (subjects, "Id", "Name", subjects. FirstOrDefault (p => p. Id == subject));viewModel = new LecturerViewModel ();. GetAllFinalGrades (db, group. Value, lecturerId, subject. Value, semester);

// Заполнения модели представления

// Получение название предметов для журнала

viewModel. GetNamesOfStudents (db, group. Value, lecturerId, subject. Value, semester);

// Получение данных для заполнения области таблицы с оценками

viewModel. GetStudentsGrades (db, group. Value, lecturerId, subject. Value, semester);

// Для строки с названиями месяцев

viewModel. GetMounthNames ();

// С количеством дней в месяцах для для colspan.

viewModel. GetDaysMounth ();

// Для отображение строки где день месяца + день недели.

viewModel. GetDaysSemester ();

// Для формирование таблиц с итоговыми оценками

viewModel. GetAllFinalGrades (db, group. Value, lecturerId, subject. Value, semester);. Subject = db. Subjects. Find (subject);. Group = db. Groups. Find (group);View (viewModel);

}

Пояснение:

Фактически тот же самый функционал что и у метода Index с той разницей, что добавлен функционал выбора семестра. Разделение на Index и Архив было сделано осознано, чтобы отделить таблицы с оценками текущего семестра от всех остальных.

Создание таблицы - журнал


Рис. 6 Создание таблицы - журнал

Исходный код:

public ActionResult CreateJournal (int groupId, int subjectId)

{. GroupId = groupId;. SubjectId = subjectId;View ();

}

[HttpPost]ActionResult CreateJournal (List<bool> numerator, List<bool> denominator, int groupId, int subjectId)

{userName = HttpContext. User. Identity. Name;db = new DiaryConnection ();lecId = db. Teachers. Where (p => p. UserName == userName). First (). Id;tgs = db. TeachersGroupsSubjects. Where (p => p. TeacherId == lecId &&. GroupId == groupId && p. SubjectId == subjectId). First ();semester = Semester. Today ();(db. TableOfGrades. Any (p => p. TeachersGroupsSubjectId == tgs. Id && p. TypeOfKnowledgeControl == "Journal"))Redirect ("/Lecturer/Index" + "/" + groupId + "/" + subjectId);

// var tgs = (from p in db. TeachersGroupsSubject where p. TeacherId == lecId /*&& p. GroupId == group1 && p. SubjectId == subject*/ select p). ToList (); // db. TeachersGroupsSubject. Where (p => p. TeacherId == lecId && p. GroupId ==group &&p. SubjectId == subject). ToList (). First ();

// Получаем все дни по расписанию в течении семестра.

var allDays = GetAllDaysAreOnTimetable (numerator, denominator, semester);

// Получаем всех студентов у данной группы

var allStudents = (from p in db. Students where p. GroupId == groupIdnew

{ Id = p. Id }). ToList (); /*db. Students. Where (p => p. GroupId == group1) */

// Добавляем новую таблицу с оценками (TGSId должен быть параметром)

var newTable = new TableOfGrades {= tgs. Id,= "Journal",= semester. Id

};. TableOfGrades. Add (newTable);. SaveChanges ();(var day in allDays)

{(var std in allStudents)

{(! db. TableEntry. Any (p => (p. StudentId == std. Id) && (p. Date == day) && (p. TableOfGradeId == newTable. Id))). TableEntry. Add (new TableEntry { StudentId = std. Id, Date = day, TableOfGradeId = newTable. Id, Value = "" });

}

}. SaveChanges ();Redirect ("/Lecturer/Index" + "/" + groupId + "/" + subjectId);

}

Пояснение:

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

Студент


Основная страница для студента с просмотром своих оценок


Рис. 7 Основная страница студента

Исходный код:

public ActionResult Index (string year, string semesterNumber)

{userName = HttpContext. User. Identity. Name;student = dbContext. Students. Where (p => p. UserName == userName). First ();

// var semester = dbContext. Semester. Where (p => p. Year == year && p. Number == semesterNumber). First ();semester = dbContext. Semester. Where (p => p. Year == year && p. Number == semesterNumber). First ();(semester==null)();viewModel = new StudentJournalViewModel ();

// Заполнения модели представления

// Получение название предметов для журнала

viewModel. GetNamesOfSubject (dbContext, student. Id, semester);

// Получение данных для заполнения области таблицы с оценками

viewModel. GetSubjectGrades (dbContext, student. Id, semester);

// Для строки с названиями месяцев

viewModel. GetMounthNames ();

// С количеством дней в месяцах для для colspan.

viewModel. GetDaysMounth ();

// Для отображение строки где день месяца + день недели.

viewModel. GetDaysSemester ();

// Для отображение пропусков ввида: ”3 пропуска из 24”

viewModel. GetMissed ();

// Для формирование таблиц с итоговыми оценками

viewModel. GetAllFinalGrades (dbContext, student. Id, semester);

// для формирования cсылок с оценками за разные семестры

viewModel. GetRefToSemesters (dbContext, student. Id); View (viewModel);

}

Пояснение:

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

Подача заявки на регистрацию студентом


Рис. 8 Форма подачи заявки на регистрацию, студентом

Исходный код:

[AllowAnonymous]ActionResult StudentRegister ()

{<Groups> groups = new List<Groups> ();(DiaryConnection db = new DiaryConnection ())

{= db. Groups. ToList ();(var b in groups)

{. Number = b. GetGroupNumber (Semester. Today ());. Groups = new SelectList (groups, "Id", "Number");

}

}View ();

}

[HttpPost]

[AllowAnonymous]ActionResult StudentRegister (StudentRegisterViewModel viewModel)

{application = new ApplicationsForRegistration {FirstName = viewModel. FirstName,= viewModel. SecondName, MiddleName = viewModel. MiddleName,= viewModel. CardNumber, DateOfBirth = viewModel. DateOfBirth,= viewModel. GroupId, Email = viewModel. Email, Login = viewModel. Login, Password = viewModel. Password };(DiaryConnection db = new DiaryConnection ())

{. ApplicationsForRegistration. Add (application);. SaveChanges ();

}RedirectToAction ("ApplicationAccepted");

}

[AllowAnonymous]ActionResult ApplicationAccepted ()

{View ();

}

Пояснение:

Студент заполняет данную форму, чтобы администратор мог его одназначно идентифицировать и принять его заявку.

Администратор

У администартора есть права на поиск, удаление, редактирование, создания основных сущностей: Студент, Группа, Преподаватель, Дисциплина, ПреподавательГруппаДисциплина, Семестр. Описывать этот функционал несколько раз - безсмысленно, поэтому расмотрим его подробнее на примере Группы.

Основная типовая страница для Группы


Рис. 9 Группа у администратора

Исходный код:

public ActionResult Groups ()

{<Groups> groups;db = new DiaryConnection ();= db. Groups. ToList ();View (groups);

}ActionResult GroupsSearch (int? number, int? yearOfAdmission, string faculty, string degree, string formOfStudy)

{<Groups> foundGroups;<Groups> groups;(DiaryConnection db = new DiaryConnection ())

{= db. Groups. ToList ();

}= groups;(number! = null)= foundGroups. Where (p => p. GetGroupNumber (Semester. Today ()) == number);(yearOfAdmission! = null)= foundGroups. Where (p => p. YearOfAdmission == yearOfAdmission);(faculty! = "")= foundGroups. Where (p => p. Faculty == faculty);(degree! = "")= foundGroups. Where (p => p. Degree == degree);(formOfStudy! = "")= foundGroups. Where (p => p. FormOfStudy == formOfStudy); PartialView (foundGroups);

}

Пояснение:

Сверху страницу строки для ввода данных для поиска и соответствующая кнопка.

Снизу отображаются найденные Группы с двумя кнопками - удалить и редактировать.

Создание Группы


Рис. 10 Создание группы

Исходный код:

[HttpGet]ActionResult AddGroups ()

{View ();

}

[HttpPost]ActionResult AddGroups ([Bind (Include = "Id,Number,YearOfAdmission,Faculty,Degree,FormOfStudy,MonitorId")] Groups groups)

{(DiaryConnection db = new DiaryConnection ())

{(ModelState. IsValid)

{. Groups. Add (groups);. SaveChanges ();RedirectToAction ("Groups");

}

}. ErrorMessage = "Неверный ввод данных"; View (groups);

}

Пояснение:

Отображаются поля для создания новой группы с валидацией на представлении и на сервере.

Редактирование Группы


Рис. 11 Редактирование группы

Исходный код:

[HttpGet]ActionResult EditGroups (int? id)

{(id == null)

{HttpNotFound ();

}group;(DiaryConnection db = new DiaryConnection ())

{= db. Groups. Find (id);(group! = null)

{students = db. Students. Where (p => p. GroupId == group. Id). ToList ();. Students = new SelectList (students, "Id", "FullName", group. Students);. Dispose ();View (group);

}

}HttpNotFound ();

}

[HttpPost]ActionResult EditGroups ([Bind (Include = "Id,Number,YearOfAdmission,Faculty,Degree,FormOfStudy,MonitorId")] Groups group)

{(DiaryConnection db = new DiaryConnection ())

{(ModelState. IsValid)

{. Entry (group). State = EntityState. Modified;. SaveChanges ();

}

{students = db. Students. Where (p => p. GroupId == group. Id);. Students = new SelectList (students, "Id", "FullName", group. Students);. Dispose ();View (group);

}

}RedirectToAction ("Groups");

}

Пояснение:

Поля формы заполнены данными выбранной группы. При нажатие кнопки “Изменить”, происходит сохранение изменений у выбранной группы.

Удаление Группы


Рис. 12 Удаление группы

Исходный код:

[HttpGet]ActionResult DeleteGroups (int? id)

{(id == null)

{HttpNotFound ();

}group;(DiaryConnection db = new DiaryConnection ())= db. Groups. Find (id);(group == null)

{HttpNotFound ();

}. Id = id;View (group);

}

[HttpPost, ActionName ("DeleteGroups")]ActionResult DeleteGroupConfirmed (int id)

{(DiaryConnection db = new DiaryConnection ())

{. Database. Log = s => System. Diagnostics. Debug. WriteLine (s);group = db. Groups. Find (id);(group == null)

{HttpNotFound ();

}. Groups. Remove (group);

{. SaveChanges ();

}(System. Data. Entity. Infrastructure. DbUpdateException ex)

{

string errorMessage = "Нельзя удалить так как данная группа используеться в одном из TeacherGroupSubject";

string url = "Groups";RedirectToAction ("ErrorMessage", new { message = errorMessage, urlToRedirect = url });

}

}

return RedirectToAction ("Groups");

}

Пояснение:

Процесс удаление разделён на 2 части.1 часть выводить форма с данными о удаляемой группе, во 2 части (метод POST) происходит само удаление. Тем самым мы спрашиваем подтверждение у пользователя об удалении.

Принятие заявки на регистрацию студента


*место для картинки*

Исходный код:

[HttpGet]ActionResult ConfirmStudentRegistration (int? id)

{(id == null)HttpNotFound ();application;db = new DiaryConnection ();= db. ApplicationsForRegistration. Find (id);. FoundStudents= db. Students. Where (p => (p. FullName. Contains (application. FirstName) && p. FullName. Contains (application. SecondName)) || p. Number == application. CardNumber). ToList ();View (application);

}

[HttpPost]ActionResult StudentsSearchForApplication (string number, string fullName, string groupNumber, int applicationId)

{<Students> foundStudents;(DiaryConnection db = new DiaryConnection ())

{(number == "" && fullName == "" && groupNumber == "")= db. Students. ToList ();if (fullName == "" && groupNumber == "")= db. Students. Where (p => p. Number == number). ToList ();if (number == "" && groupNumber == "")= db. Students. Where (p => p. FullName. Contains (fullName)). ToList ();if (number == "" && fullName == "")

{students = db. Students. ToList ();= students. Where (p => p. Groups1. GetGroupNumber (Semester. Today ()) == Convert. ToInt32 (groupNumber)). ToList ();

}if (groupNumber == null)= db. Students. Where (p => p. Number == number && p. FullName. Contains (fullName)). ToList ();if (number == "")= db. Students. Where (p => p. FullName. Contains (fullName)). ToList ().(p => p. Groups1. GetGroupNumber (Semester. Today ()) == Convert. ToInt32 (groupNumber)). ToList ();if (fullName == "")= db. Students. Where (p => p. Number == number). ToList ().(p => p. Groups1. GetGroupNumber (Semester. Today ()) == Convert. ToInt32 (groupNumber)). ToList ();

{= db. Students. Where (p => p. Number == number && p. FullName. Contains (fullName)). ToList ().(p => p. Groups1. GetGroupNumber (Semester. Today ()) == Convert. ToInt32 (groupNumber)). ToList ();

}. RemoveAll (p => p. UserName! = null);

}. ApplicationId = applicationId;PartialView (foundStudents);

}ActionResult CompletionStudentRegistration (int? applicationId, int? studentId)

{(applicationId == null || studentId == null)HttpNotFound ();db = new DiaryConnection ();application = db. ApplicationsForRegistration. Find (applicationId);. FoundStudents = db. Students. Where (p => (p. FullName. Contains (application. FirstName) && p. FullName. Contains (application. SecondName)) || p. Number == application. CardNumber);student = db. Students. Find (studentId);context = new ApplicationDbContext ();userManager = new ApplicationUserManager (new UserStore<ApplicationUser> (context));studentAccount = new ApplicationUser { Email = application. Email, UserName = application. Login };result = userManager. Create (studentAccount, application. Password);(result. Succeeded)

{. AddToRole (studentAccount. Id, "student");. UserName = application. Login;. ApplicationsForRegistration. Remove (application);. SaveChanges ();

}RedirectToAction ("ApplicationsForRegistration");

}

Пояснение:

Студент оставляет свою заявку на регистрацию, затем администратор должен одобрить её или отклонить. На представление админстратор видит справа выбранную заявку, а слева функционал выбора студента с которым надо связать заявку. В функционал входят: возможность поиска студента, и список найденных студентов в который изначально включены. Рядом с найденным студентом стоит кнопка которая связывает заявку со студентом т.е. создаёт аккаунт для студента (с логином и паролем указанным в заявке).

5. Тестирование


Запуск веб-приложения происходить с помощью браузера ‘Яндекс. Браузер’.

Тест 1.

У каждого аккаунта в этом веб-приложении есть своя роль. Всего их 3 - это студент, преподаватель и администратор, и в зависимости от того какая роль у аккаунта приложение предоставляет соответствующий этой роли функционал.

Авторизация за студента.

Результат: отображается соответствующий именно этому студенту таблицы.

Тест 2. Отображения разных таблиц с оценками для студента в зависимости от выбранного семестра.

Результат: Отображаемые таблицы изменяются в зависимости от выбранного семестра.

Тест 3. Подачи заявки на регистрацию студентом.

Рис. 13 Тестирование подачи заявки на регистарцию

Результат: после нажатия Регистрация соответствующая заявка сохранена в бд и ждёт подтверждения администратором.

Рис. 14 Заявка на регистрацию в БД

Тест 4.

Авторизация за преподавателя.

Результат: отображается соответствующий этой роли функционал, так же таблицы, группы и предметы соответствующую именно этому преподавателю.

Рис. 15 Результат авторизации за преподавателя

Тест 5.

Внесение изменений в поля таблицы и сохранение этих изменений в бд.

Внесём в пустую таблицу с оценками за экзамен какие-либо оценки.

Рис. 16 Таблица с оценками

Если нажать сохранить, то данные изменения в таблице сохраняться в бд и при обновление страницы, таблица будет с новыми данными.

Тест 6. При выборе других групп и дисциплин отображаются соответствующие именно им таблиц.

Результат: Таблицы с оценками отображаются для выбранных Групп и Дисциплин.

Тест 7. Создание связи ПреподавательГруппаДисциплина.

Создание этой связи обозначает, что Преподаватель из этой связи ведёт у Группы из этой связи указанную Дисциплину.

Рис. 17 Тестирование создание связи ПреподавательГруппаПредмет

Если нажать добавить, то создаться необходимая связь и можно будет создать таблицы для этой группы и предмета.

Рис. 18 Результат создания связи ПреподавательГруппаПредмет

Тест 8. Создание таблиц с оценками.

Изначально никаких таблиц нету и преподаватель должен создать необходимые ему таблицы.

Рис. 19 Создание таблиц

При нажатие на одну из ссылок создаётся нужная таблица.

Рис. 20 Результат создания таблицы

Результат: создана нужная таблица.

Тест 9. Авторизация за администратора.

Рис. 21 Пример страницы для администратора

Результат: После авторизации открывается функционал администратора.

Тест 10. Поиск Групп.

Поиск происходит по полям: Номер группы, Год поступление, Факультет, Ступень, Форма обучения.

Рис. 22 Пример поиска группы

Результат: поиск удался.

Тест 11. Создание группы.

Рис. 23 Создание группы

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

Рис. 24 Результат создание группы

Результат: Группа создана.

Тест 12. Редактирование Группы.

Для этого надо найди нужную Группу и нажать соответствующую кнопку.

Рис. 25 Группа с подчёркнутой кнопкой для редактирования

Выводится форма с полями для редактирование.

Рис. 26 Форма для редактирование Группы

Если эти поля изменить и изменение пройдут валидацию, то сохранения вступят в силу.

Рис. 27 Результат реадктирования Группы

Результат: Студент успешно отредактирован.

Тест 13. Удаление Группы.

Для удаление нужно найти нужного Студента, и нажать нужную кнопку.

Рис. 28 Группа с подчёркнутой кнопкой для удаление

Появиться форма с предложением удалить Группу, если нажать Удалить, то Группа удалится.

Рис. 29 Форма с предложением удалить Группу

Результат: Студент успешно удалён.

Рис. 30 Результат удаление Группы

Тест 14. Приём заявки регистрации студента.

Рис. 31 Заявка на регистрацию с подчёркнутой кнопкой для выбора заявки

Сначала нужно выбрать заявку, которую собираемся принять и нажать нужную кнопку.

Рис. 32 Страница для принятие заявки

Затем, выбрать того студента с которым собираемся связать заявку. Для этого можно использовать функционал поиска или выбрать одного из найденных студентов и нажат рядом с ним на кнопку, тогда произойдёт связывание заявки на регистрацию и Студента и выбранный студент получит возможность проходить аутентификацию и авторизацию на сайте.

6. Руководство пользователя


Окно логина

При первом заходе на веб-приложение его встречает окно для ввода логина и пароля.

Рис. 33 Окно логина

И в зависимости от вида пользователя этой учётной записи, функционал веб-приложения может принимать 3 формы:

1)      Студент

2)      Преподаватель

)        Администратор

 

6.1 Студент


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

Студент может оставить заявку на регистрацию, которую потом администратор может принять и активировать для этого студента функционал аутентификации и авторизации.

На этом функционал для студента исчерпывается.

6.2 Преподаватель


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

Рис. 34 Журнал для Преподавателя

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

Как видно вверху есть закладка Преподаватель-Группа-Предмет. Она служит для того что бы преподаватель мог выбрать у какой группы и какой предмет он введёт.

Преподаватель может выбрать уже существующий предмет или создать новый.

Сверху есть ещё одна закладка Архив. В архиве хранятся оценки студентов за предыдущие семестры (в Журнале только за текущий).

Рис. 35 Архив у Преподавателя

Тот же самый функционал что и в Журнале, только с выбором семестра.

Преподаватель может выбрать какие таблицы (экзамен, зачёт, практика и тп) ему создать.

Рис. 36 Создание таблиц

Общее руководство для преподавателя

В самом начале использование приложением преподавателю нужно выбрать те группы и предметы у которых он введёт в этом семестре, затем создать необходимые таблицы по этим таблицам.

 

6.3 Администратор


После прохождения аутентификации и авторизации, администратор видит страницу для работы со Студентами.

Рис. 37 Страница для работы со студентами

Это типовой вариант для страницы, подобная страница есть для таких сущностей как Студент, Предмет, Преподаватель, Группа, Семестр, Преподаватель-Группа-Предмет.

·        Поиск

·        Создание

·        Редактирование

·        Удаление

Поиск

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

Создание

При нажатие на кнопку Добавить студента, открывается страница для создания Студента с соответствующими полями.

Рис. 38 Создания студента

Редактирование

Что бы редактировать студента нужно нажать на подчёркнутую кнопку в списке найденных студентов.

Рис. 39 Кнопка для редактирование Студента

Тогда открывается форма для редактирование полей студента.

Рис. 40. Редактирование студента

Удаление

Что бы удалить студента нужно нажать на подчёркнутую кнопку в списке найденных студентов.

Рис. 41 Кнопка для удаление Студента

Тогда открывается форма с подтверждением удаление Студента.

Рис. 42 Подверждение удаление студента

Приём заявок на регистрацию студента

Для начала нужно выбрать нужную заявку которую мы хотим одобрить. А затем найти того студента которым она была написана и нажать нужную кнопку.

Журнал

Администратор может и изменять, ставить и удалять оценки в таблицах. Функционал подобен Преподавателю, только с выбором преподавателя.

Общее руководство для администратора

При начале использование веб-приложением администратору нужно создать необходимые сущности для нормальной работы приложения. Начать нужно с создание Семестра, затем ввести необходимые Группы, уже потом вводить Студентов.

7. Руководство по установке и сопровождению ПО


Для того чтобы управлять сайтом после его создания, изменять и расширять функциональность, разработчик должен:

•        Представлять себе принципы работы с реляционной СУБД MS SQL server.

•        Знать принципы создания сайтов ASP.net на языке C#.

Также необходимо знать основы языка программирования JavaScript с фреймворком jQuery, языки запросов SQL, язык разметки HTML, иметь представление о технологии CSS.

Программные требования

операционная система Microsoft Windows; webсервер c поддержкой хостинга ASP.net; сервер баз данных MS SQL 2014 или выше

Хранение данных

Данные должны храниться в БД на выбранном хостинге. Важное замечание что для работы этого веб-приложения нужно чтобы хостинг поддерживал минимум 2 БД. Одна для таблиц из предметной области, а другая для системы аутентификации и авторизации Identity.

Публикация на веб-сервере IIS

Данная публикация проводилась на Visual Studio 2015 Community и ОС Windows 8.

Как правило, большинство веб-приложений ASP.net публикуются на веб-сервер IIS. Поэтому посмотрим на примере, как размещать веб-приложение на IIS-севере.

В начале сконфигурируем веб-сервер. Для этого откроем средство администрирования IIS: зайдем в Панель управления, затем выберем Администрирование->Диспетчер служб IIS. И нам откроется консоль управления IIS:

Рис. 43 IIS

Будем размещать свой сайт в узле по умолчанию (в моем случае это Default Web Site). И для этого вначале создадим в каталоге этого узла папку для нашего приложения. По умолчанию каталогом для стандартного веб-узла является каталог C: \inetpub\wwwroot. Перейдем в нее и создадим в нем папку Diary, которая будет содержать наше приложение.

Теперь нажмем правой кнопкой мыши на имя узла по умолчанию и выберем в появившемся меню пункт Добавить приложение:

Рис. 44 Где находится добавление приложения в IIS.

В появившемся окне введем соответствующие настройки (в качестве физического пути приложения созданный выше каталог):

Рис. 45 Добавление приложения в IIS.

Сайт у нас практически создан. Теперь осталось разместить в каталоге C: \inetpub\wwwroot\Diary наше приложение.

Перейдем к приложению в Visual Studio. Сверху откроем закладку Сборка и в появившемся меню выберем Опубликовать:

Перед нами откроется мастер публикации, который предложит нам пройти несколько этапов. В начале выберем профиль. Новый профиль можно создать нажав “Настроить”.

Рис. 46 Настройка публикации проекта

После создания профиля нажмем на Далее и перейдем к следующему этапу - Подключение. На этом этапе для опции Publish Method выберем File System

Для опции Target Location определим физический путь к каталогу нашего сайта. В данном случае это путь C: \inetpub\wwwroot\Diary.

Рис. 47 Настройка подключения для опубликование проекта

После установки всех свойств жмем на кнопку Опубликовать. После этого в Visual Studio в окне Вывод студия выдаст сводку об успешности или неуспешности публикации. Возможно, вы увидите сообщения "Отказано в доступе", из-за чего публикация пройдет неудачно:

В этом случае нам надо открыть доступ к папке C: \inetpub\wwwroot\Diary на запись (по умолчанию стоит доступ только на чтение) и повторить публикацию.

Либо как вариант, если мы не хотим раскрывать доступ на запись, то можно вручную скопировать и перенести все необходимые файлы в указанную выше папку. Как нам показывает окно Output, все файлы для публикации сохраняются в проекте в каталоге obj\Release\Package\PackageTmp. И мы можем просто скопировать все файлы из этого каталога и перенести их в каталог C: \inetpub\wwwroot\Diary.

Если мы при создании веб-приложения использовали движок базы данных localdb, то нам надо разместить базу данных на MS SQL Server и соответсвенно изменить строку подключения к базе данных, чтобы использовать уже не localdb, который предназначен только для целей разработки, а MS SQL Server.

Теперь запустим Службу веб-публикаций через консоль Служб или через консоль IIS и можем обращаться к сайту по url http://localhost/Diary.

Заключение

В выпускной квалифицированной работе были решены следующие задачи.

)        Была проанализирована предметная область. С помощью этого анализа были разработаны требования к системе и архитектуре приложения.

2)      При проектировании была разработана схема БД соответствующая предметной области и требованиям к системе. Написан сценарий работы приложения, по которому велась разработка приложения.

3)      На этапе реализации было разработана серверная часть веб-приложения с помощью фреймворка ASP.net MVC 5. Была разработана БД средствами Visual Studio 2015 и MS SQL Server 2016.

)        Было проведено тестирование и отладка веб-приложения, которая подтверждает эффективную работу веб-приложения.

Список используемых источников


1. Горавнева, Т.С., Петров О.Н. Интернет-технологии. Часть 1. Клиентское web-программирование. Учебное пособие, - СПб.: СПбГМТУ, 2012.

. Горавнева, Т.С., Петров О.Н. Интернет-технологии. Часть 2. XML и AJAX. Учебное пособие, - СПб.: СПбГМТУ, 2012.

. Горавнева, Т.С., Петров О.Н. Интернет-технологии. Часть 3.html5 и CSS3. Учебное пособие, - СПб.: СПбГМТУ, 2014.

4. Горавнева, Т.С., Петров О.Н. Интернет-технологии. Часть 1. Клиентское web-программирование. [URL] http://bk. smtu.ru/books/13169UP/index. htm

. Горавнева, Т.С., Петров О.Н. Интернет-технологии. Часть 2. XML и AJAX. [URL] http://bk. smtu.ru/books/13170UP/index. htm <https://vk.com/away.php?to=http%3A%2F%2Fbk.smtu.ru%2Fbooks%2F13170UP%2Findex.htm&cc_key=>

6. Горавнева, Т.С., Петров О.Н. Интернет-технологии. Часть 3.html5 и CSS3. [URL] http://bk. smtu/books/13225UP/index. htm <https://vk.com/away.php?to=http%3A%2F%2Fbk.smtu%2Fbooks%2F13225UP%2Findex.htm&cc_key=>

7. Квинт, И. Создаем сайты с помощью HTML, XHTML и CSS на 100% - СПб.: Питер, 2012.

. Спецификация языка HTML. Учебный курс / пер. с анг.А. Пирамидина; Интернет-университет информационных технологий. [URL]: http://www.intuit.ru/department/internet/html

. Сычев, А. Перспективные технологии и языки веб-разработки: [URL]: http://www.intuit.ru/studies/courses/2336/636/info

. Хоган, Уоррен, Уэбер, Джонсон, Годин. Книга веб-программиста. Секреты профессиональной разработки веб-сайтов - СПб.: Питер, 2013.

. Сайт посвященый различным языкам и технологиям программирования, компьютерам, мобильным платформам и ИТ-технологиям [Электронный ресурс] [URL]: https: // metanit.com

. Сеть разработчиков Microsoft [Электронный ресурс] [URL]: https: // msdn. microsoft.com/

. Многофункциональный сайт, представляющий собой смешение новостного сайта и коллективного блога, созданный для публикации новостей, аналитических статей, мыслей, связанных с информационными технологиями, бизнесом и Интернетом [Электронный ресурс] [URL]: https: // habrahabr.ru/

Похожие работы на - Онлайн-дневник студента

 

Не нашли материал для своей работы?
Поможем написать уникальную работу
Без плагиата!