Управление списками разрешённых направлений
Федеральное
государственное бюджетное образовательное учреждение высшего профессионального
образования Национальный исследовательский университет «МЭИ»
Отчет
к курсовому
проекту
по дисциплине
«Базы данных»
Тема:
«Управление списками разрешённых направлений»
Студент группы А-16-09:
Чаплыгин Д.И.
Преподаватель:
доц., к.т.н. Сидорова Н.П.
Москва 2013
г.
Оглавление
Задание на курсовой проект
Исходные данные для выполнения курсового проекта
Сокращения
Введение
. Анализ предметной области
. Проектирование базы данных
.1. Разработка ER-модели
.2. Проектирование правил целостности БД
.3. Анализ реляционной модели
. Реализация базы данных
. Программная реализация
.1 ADO .NET и Entity Framework
.2 Примеры экранных форм интерфейса
Литература
Приложение 1. Программный код, содержащий функции
взаимодействия с БД.
Задание на
курсовой проект
Цель работы: разработка и написание ПО а также проектирование и
реализация элементов БД для автоматизации организации работы с направлениями
подготовки в учебных заведениях высшего и среднего-профессионального
образования.
БД должна выполнять следующие задачи:
· Формировать список заявок от различных пользователей,
содержащих достаточную для системы информацию касающуюся самого пользователя
(учебного заведения), набора его направлений.
· Поддерживать рабочий интерфейс с уже реализованными
компонентами БД (связи по внешнему ключу).
· Поддерживать целостность работы системы.
· Иметь возможность сохранять отклики (комментарии)
пользователей и администраторов системы о причинах и результатах оформления
заявок.
Исходные
данные для выполнения курсового проекта
Среда реализации: Microsoft Visual Studio 2010;
СУБД: Microsoft SQL;
Сервер ASP.NET MVC, .Net
4.0 IIS;
Интерфейс работы с БД: Entity Framework, LinQ;
Среда проектирования БД: Allfusion ERWin.
Сокращения
БД - база данных
НФ - третья нормальная форма
СУБД - система управления базами данных
ФЗ - функциональная зависимость
ФИС ЕГЭ и приёма, система - Федеральная информационная служба
Рособрнадзора о проведении Единого Государственного Экзамена и порядка приёма.
УЗ - учебное заведение (соотв. ВУЗ и ССУЗ - Высшее УЗ и Среднее
спеиальное УЗ), пользователь системы ФИС.
Введение
Целью курсового проекта является разработка моделей базы данных (БД) и
интерфейсных средств для выполнения указанных в задании функций. БД
обеспечивает хранение информации и представляет собой поименованную
совокупность данных, организованных по определенным правилам, включающим общие
принципы описания, хранения и манипулирования данными. БД является
информационной моделью предметной области, в которой решаются поставленные
задачи.
Этапы выполнения курсового проекта:
· поведение анализа предметной области;
· проектирование БД;
· реализация БД средствами выбранной СУБД;
· программная реализация интерфейса с БД.
Для анализа предметной области используется CASE-средство AllFusion
Process Modeler, который входит в состав пакета AllFusion Modeler Suite.
Проектирование моделей БД выполняется с помощью CASE-средства AllFusion ERwin
Data Modeler, входящий в состав этого же пакета.
Реализация БД проводится в среде Microsoft SQL Server. В качестве языка
реализации был выбран C# в среде Microsoft Visual Studio.
1. Анализ
предметной области
1.1 Описание предметной области
Управление списками разрешённых направлениями: для каждого Уза
предусмотрен список направлений, по которому он может проводить набор студентов
для их обучения. В системе эти направления не могут редактироваться
непосредственно УЗом, но могут редактироваться администраторами системы ФИС.
Реализация общения между Узами и администраторами построена на заявках,
содержащих всю необходимую информацию и хранящихся в БД. Заявки могут быть на
добавление специальностей в список, таки на удаление их.
Предусмотрены комментарии пользователей о причине добавления/удаления
(как пример: приказ), так и комментарии администраторов в случае отказа
выполнения заявки. Доступ к комментариям должен сохраняться в независимости от
результата обработки заявки.
Количество комментариев к одному направлению от одного пользователя
неограниченно.
У одного УЗа может быть указано в заявке теоретически неограниченное
количество направлений, причём на удаление могут указываться только
направления, уже разрешённые для этого УЗа и, при этом, не входящие в
конкурсные группы его незавершённых приёмных кампаний.
1.2 Определение объектов модели
Анализ построенных моделей позволил выделить информационные объекты
предмтеной области. Состав и характеристика информационных объектов приведена в
табл. 1.
Таблица 1. Информационные объекты и их свойства
Имя объекта
|
Описание объекта
|
Свойства объекта
|
Запрос на редактирование списка.
|
Содержит полную информацию о направлении и действии,
которое необходимо произвести.
|
Номер запроса Номер направления Вид набора Действие Статус
заявки Дата создание заявки Дата изменение статуса заявки
|
Комментарий к заявке
|
Содержит ветвь комментариев к каждому направлению каждого
института. Необязательный атрибут.
|
Номер комментария Комментатор Дата создания комментария
Номер интститута Номер направления
|
2. Проектирование
базы данных
Проектирование БД предполагает разработку моделей нескольких типов:
· Реляционная модель, которая формируется на основе модели
«сущность - связь».
2.1 Разработка ER-модели
база данные предметный проектирование
На основе выделенных информационных объектов средствами Microsoft Visio была построена модель «сущность - связь» (рис. 2.1.).
Рис. 2.1. Модель «сущность-связь» для БД
Описание атрибутов таблицы «Заявка»:
Номер заявки - целое число, ненулевой тип, ключевой параметр, является
внешним ключом (атрибут таблицы Институт - Номер института),
Номер направления - целое число, ненулевой тип, ключевой параметр,
является внешним ключом (атрибут таблицы Направление подготовки - Номер
направления),
Действие - строка, ненулевая, длина - 3,
Статус - строка, ненулевая, длина - 1,
Тип приёма набора - целое число, ненулевое,
Дата создания заявки - дата, необязательный атрибут,
Дата изменения заявки - дата, необязательный атрибут.
Описание атрибутов таблицы «Комментарий»:
Номер комментария - целое число, ненулевой тип, ключевой параметр,
Номер направления - целое число, ненулевой тип, является внешним ключом
(атрибут таблицы Заявка - Номер направления),
Номер института - целое число, ненулевой тип, является внешним ключом
(атрибут таблицы Заявка - Номер заявки),
Комментатор - строка, ненулевая,
Комментарий - строка, необязательный атрибут,
Дата добавления комментария - дата, необязательный тип.
2.2 Проектирование
правил целостности БД
Поле
|
Правило целостности
|
Действие
|
Может принимать только значения 'ADD' или ‘DEL’
|
Статус
|
Может принимать только значения 'A', 'D' или 'W'
|
Номер направления
|
Больше нуля
|
Номер комментария
|
Больше нуля
|
Номер заявки
|
Больше нуля
|
Тип приёма набора
|
Число от 1 до 10
|
Все поля типа Date
|
Не ранее 01.01.2013
|
2.3 Анализ
реляционной модели
Рис. 2.2 Реляционная модель БД
Для получения хороших характеристик работы с БД, она должна находиться в
3НФ. Для проверки этого необходимо обеспечить атомарность атрибутов, выделить
функциональные зависимости (ФЗ) между атрибутами в каждом отношении и провести
их анализ.
Отношение Request
Direction, ключ отношения:
Request ID - Внешний ключ отношения Institution, атрибут InstitutionID,- Внешний ключ отноения Direction, атрибут DirectionID.
Функциональные зависимости: ID, DirectionID →
Activity,ID, DirectionID → Action,ID, DirectionID → ChangedDate,ID,
DirectionID → CreationDate,→ AdmissionItemType.
Отношение RequestComments, ключ отношения:ID.
Функциональные зависимости:→ Commentor,→ Comment,→
Date,→ DirectionID,→ InstitutionID.
Других ФЗ для отношений не выявлено. Обоснование нахождения БД в 3НФ
предполагает проверку ограничений, накладываемых в 3НФ.
. Все таблицы БД находятся в 1НФ, их поля содержат атомарные значения.
. Полная ФЗ неключевых атрибутов от ключа для RequestComments обеспечивается тем, что ключ в этом
отношении простой.
. Для отношения RequestDirection полная ФЗ между неключевыми атрибутами и
составным ключом существует.
. В разработанных отношениях отсутствуют транзитивные зависимости.
Следовательно, БД находится в 3НФ.
3. Реализация
базы данных
В качестве СУБД для реализации БД в курсовом проекте была выбрана СУБД
Microsoft SQL Server. Эта СУБД разработана корпорацией Microsoft и поддреживает
реляционную модель БД. Основной используемый язык запросов - Transact-SQL,
созданный совместно Microsoft и Sybase. Transact-SQL является реализацией
стандарта ANSI/ISO структурированного языка запросов (SQL) с расширениями. СУБД
SQL Server используется для работы со средними и большими БД. Ниже приведено
описание БД средствами Transact-SQL.
SET ANSI_NULLS ON
GOQUOTED_IDENTIFIER ONANSI_PADDING ONTABLE
[dbo].[RequestDirection](
[Direction ID] [int] NOT NULL,
[Request ID] [int] NOT NULL,
[Activity] [varchar](1) NOT NULL,
[Action] [varchar](10) NOT NULL,
[AdmissionItemType] [int] NOT NULL,
[CreationDate] [datetime] NULL,
[ChangeDate] [datetime] NULL,[PK_RequestDirection] PRIMARY
KEY CLUSTERED
(
[Direction ID] ASC,
[Request ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]ANSI_PADDING OFFTABLE [dbo].[RequestDirection]
WITH CHECK ADD CONSTRAINT [FK_RequestDirection_Request] FOREIGN KEY([Request
ID])[dbo].[Institution] ([InstitutionID])TABLE [dbo].[RequestDirection] CHECK
CONSTRAINT [FK_RequestDirection_Request]ANSI_NULLS ONQUOTED_IDENTIFIER
ONANSI_PADDING ONTABLE [dbo].[RequestComments](
[Comment ID] [int] NOT NULL,
[Commentor] [varchar](5) NOT NULL,
[Comment] [text] NULL,
[Date] [datetime] NULL,
[DirectionID] [int] NOT NULL,
(
[Comment ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]ANSI_PADDING OFFTABLE
[dbo].[RequestComments] WITH NOCHECK ADD CONSTRAINT
[FK_RequestComments_RequestDirection] FOREIGN KEY([DirectionID],
[InstitutionID])[dbo].[RequestDirection] ([Direction ID], [Request ID])TABLE
[dbo].[RequestComments] NOCHECK CONSTRAINT
[FK_RequestComments_RequestDirection]
GO
4.
Программная реализация
Для реализации приложения с БД выбран язык С# и технология ADO.NET Entity
Framework.
4.1 ADO .NET и
Entity Framework
.NET является набором классов,
реализующих программные интерфейсы для облегчения подключения к БД из
приложения, независимо от особенностей реализации конкретной СУБД. ADO .NET
широко используется совместно с технологией web-программирования с
использованием объектов ASP .NET для доступа к расположенным на сервере базам
данных со стороны клиента.
Объектная модель ADO .NET реализует отсоединенный доступ к данным. При
этом в Visual Studio .NET существует множество встроенных мастеров и
дизайнеров, которые позволяют реализовать механизмы доступа к БД еще на этапе
разработки программного кода. С другой стороны, задача получения доступа к
данным может быть решена непосредственно во время выполнения приложения.
Концепция доступа к данным в ADO .NET основана на использовании двух
компонентов:
• набора данных (представляется объектом класса DataSet) со стороны
клиента. Это локальное временное хранилище данных;
• провайдера данных (представляется объектом класса DataProvider). Это
посредник, обеспечивающий взаимодействие приложения и базы данных со стороны базы
данных (в распределенных приложениях - со стороны сервера).
Объектная модель ADO .NET предполагает существование (при написании
приложения для работы с базой данных - использование) двух множеств классов,
выполняющих четко определенные задачи при работе с базой данных.
Платформа Entity Framework позволяет разработчикам создавать приложения
для доступа к данным, работающие с концептуальной моделью приложения, а не
напрямую с реляционной схемой хранения. Цель состоит в уменьшении объема кода и
снижении затрат на сопровождение приложений, ориентированных на обработку
данных. Приложения Entity Framework предоставляют следующие преимущества.
Приложения могут работать концептуальной моделью в терминах предметной
области - в том числе с наследуемыми типами, сложными элементами и связями.
Приложения освобождаются от жестких зависимостей от конкретного ядра СУБД
или схемы хранения.
Сопоставления между концептуальной моделью и схемой, специфичной для
конкретного хранилища, могут меняться без изменения кода приложения.
Разработчики имеют возможность работать с согласованной моделью объектов
приложения, которая может быть сопоставлена с различными схемами хранения,
которые, возможно, реализованы в различных системах управления данными.
Несколько концептуальных моделей могут быть сопоставлены с единой схемой
хранения.
Поддержка запросов LINQ обеспечивает проверку синтаксиса во время
компиляции для запросов к концептуальной модели.
Платформа Entity Framework впервые появилась как часть платформы .NET
Framework и выпуске Microsoft Visual Studio. Начиная с Entity Framework версии
4.1 платформа Entity Framework не является частью .NET Framework, но построена
на ее основе.
.2 Примеры
экранных форм интерфейса
Рис. 4.1 Форма добавления комментария Администратором системы в случае
отказа выполнения заявки
Рис. 4.2 Таблица направлений указанных в заявке на выбранное ОУ
Рис. 4.3 Список ОУ, у которых есть заявки
Рис. 4.4 Интерфейс добавления направлений в заявку
Рис. 4.5 Кнопка вызывающая интерфейс заполнения заявки у пользователя
Рис. 4.6 Список направлений в заявке (интерфейс пользователя)
Рис. 4.7 Список разрешённых направлений после выполнения заявки
Литература
1.
Microsoft Development network http://msdn.microsoft.com/en-US/
2. Н.П.
Сидорова. Базы данных. Методическое пособие к курсовому проектированию. - М.:
Изд-во МЭИ, 2010. - 40 с.
. Рихтер Дж.
CLR via C#. Программирование на платформе Microsoft .NET Framework 4.0 на языке
C#. - Переводчик: Радченко И., Рузмайкина И., «Питер», 2012 - 928 с.
Приложение 1.
Программный код, содержащий функции взаимодействия с БД
Контроллёры - пользователь ОУ:
[HttpPost]
[Authorize(Roles = UserRole.EduAdmin)]AjaxResultModel
RequestDisabled()
{(InstitutionsEntities dbContext = new
InstitutionsEntities())
{new AjaxResultModel { Data =
(dbContext.RequestDirection.Any(x => x.Activity == "A")) };
}
}
[HttpPost]
[Authorize(Roles = UserRole.EduAdmin)]ActionResult
CancelRequest(string directionID)
{(InstitutionsEntities dbContext = new
InstitutionsEntities())
{dir = Convert.ToInt32(directionID);
//IQueryable<int> tlist = dbContext.Request.Where(x
=> x.InstitutionID == InstitutionID).Select(x => x.ID_Request);toCancel =
dbContext.RequestDirection.Where(x => x.Direction_ID == dir &&
x.Request_ID == InstitutionID).First();(toCancel.Activity == "W")
{.DeleteObject(toCancel);.SaveChanges();
// TODO: Finish Comment Deletingnew AjaxResultModel();
}new AjaxResultModel("Данное направление в данный момент обрабатывается администратором.");
}
}
[HttpPost]
[Authorize(Roles = UserRole.EduAdmin)]ActionResult
AllowedDirectionsGetAvailableEdu(AllowedDirectionAddViewModel model)
{(InstitutionsEntities dbContext = new
InstitutionsEntities())
{dbContext.GetRemainedAvailableAllowedDirections(model,
InstitutionID);
}
}
[HttpPost]
[Authorize(Roles = UserRole.EduAdmin)]ActionResult
AllowedDirectionsGetExistingEdu(AllowedDirectionAddViewModel model)
{(InstitutionsEntities dbContext = new
InstitutionsEntities())
{dbContext.GetAllowedDirections(model, InstitutionID);
}
}
[HttpPost]
[Authorize(Roles = UserRole.EduAdmin)]ActionResult
RequestDirectionListDenied()
{(InstitutionsEntities dbContext = new
InstitutionsEntities())
}
}
[HttpPost]
[Authorize(Roles = UserRole.EduAdmin)]ActionResult
ClearAllDenied()
{(InstitutionsEntities dbContext = new
InstitutionsEntities())
{dbContext.DeleteDenied(InstitutionID);
}
}
[HttpPost]
[Authorize(Roles = UserRole.EduAdmin)]ActionResult
AllowedDirectionsDeleteEdu()
{(InstitutionsEntities dbContext = new
InstitutionsEntities())
{model =
dbContext.FillAllowedDirectionAddModel();PartialView("Admission/DeleteAllowedDirectionEdu",
model);
}
}
[HttpPost]
[Authorize(Roles = UserRole.EduAdmin)]ActionResult
RequestDirectionListToAdd()
{(InstitutionsEntities dbContext = new
InstitutionsEntities())
{dbContext.GetRequestedToAddDirections(InstitutionID);
}
}
[HttpPost]
[Authorize(Roles = UserRole.EduAdmin)]ActionResult
RequestDirectionListToDelete()
{(InstitutionsEntities dbContext = new
InstitutionsEntities())
{dbContext.GetRequestedToDeleteDirections(InstitutionID);
}
}
[HttpPost]
[Authorize(Roles = UserRole.EduAdmin)]ActionResult
DeleteDirectionRequest(int? directionid, string comment, int? admissiontype)
{DirID = directionid ?? 0;AdType = admissiontype ?? 0;(DirID
== 0) return new AjaxResultModel("");(AdType == 0) return new
AjaxResultModel("");(InstitutionsEntities dbContext = new
InstitutionsEntities())
{(EntrantsEntities dbContext1 = new EntrantsEntities())
{(dbContext1.IsInCompetitiveGroup(InstitutionID, DirID,
AdType))
{s = dbContext.Direction.Where(x => x.DirectionID ==
DirID).Select(x => x.Name).Single().ToString();
//return new AjaxResultModel(@"Нельзя удалить направление
""" + s + @""" т.к. оно содержится в конкурсных
группах.");
return new AjaxResultModel(s);
}
}
{req =
Model.Institutions.RequestDirection.CreateRequestDirection(DirID,
InstitutionID, "W", "Delete",
AdType);.RequestDirection.AddObject(req);.SaveChanges();y;
/*try
{*/= dbContext.RequestComments.Select(x =>
x.Comment_ID).Count();
/*}(System.InvalidOperationException)
{ y = 0; }*/rc =
Model.Institutions.RequestComments.CreateRequestComments(y + 1, "U",
DirID, InstitutionID);;.Comment = comment;.RequestComments.AddObject(rc);.SaveChanges();
}(System.Data.UpdateException)
{new AjaxResultModel();
}new AjaxResultModel();
}
}
[HttpPost]
[Authorize(Roles = UserRole.EduAdmin)]ActionResult
AddDirectionRequest(int? directionid, string comment, int? admissiontype)
{(directionid == null) return new
AjaxResultModel();(InstitutionsEntities dbContext = new InstitutionsEntities())
{
{req =
Model.Institutions.RequestDirection.CreateRequestDirection(directionid ?? 0,
InstitutionID, "W", "Add", admissiontype ??
0);.RequestDirection.AddObject(req);
//dbContext.SaveChanges();y;
/*try
{*/= dbContext.RequestComments.Count();
/*}(System.InvalidOperationException)
{ y = 0; }*/rc =
Model.Institutions.RequestComments.CreateRequestComments(y + 1, "U",
directionid ?? 0, InstitutionID);.Comment =
comment;.RequestComments.AddObject(rc);.SaveChanges();
}(System.Data.UpdateException)
{
}new AjaxResultModel();
}
}
[HttpPost]
[Authorize(Roles = UserRole.EduAdmin)]ActionResult
AllowedDirectionsAddEdu()
{(InstitutionsEntities dbContext = new
InstitutionsEntities())
{model =
dbContext.FillAllowedDirectionAddModel();PartialView("Admission/AddAllowedDirectionEdu",
model);
}
}
Функции из файлов расширения:
public static AjaxResultModel GetAllowedDirections(this InstitutionsEntities
dbContext, AllowedDirectionAddViewModel model, int institutionID)
{existing = dbContext.AllowedDirections
.Where(x => x.InstitutionID == institutionID &&
x.AdmissionItemTypeID == model.EducationLevelID && x.Direction.ParentID
== model.ParentDirectionID)
// выбираем по коду квалификации, который зависит от уровня образования
if (model.EducationLevelID == EDLevelConst.Bachelor).Add("62");(model.EducationLevelID
== EDLevelConst.BachelorShort).Add("62");(model.EducationLevelID ==
EDLevelConst.Magistracy).Add("68");(model.EducationLevelID ==
EDLevelConst.SPO)
{.Add("51");.Add("52");
}(model.EducationLevelID == EDLevelConst.Speciality).Add("65");avail
=.Direction.Where(x => x.ParentID == model.ParentDirectionID &&
existing.Contains(x.DirectionID))
.OrderBy(x => x.Code)
.Select(x => new { ID = x.DirectionID, Code = x.Code, Name
= x.Name, Period = x.PERIOD, x.QUALIFICATIONCODE }).ToArray()
.Where(x => qualCodes.Contains((x.QUALIFICATIONCODE ??
"").Trim()))
.Select(x => new { ID = x.ID, Code = x.Code,
QualificationCode = x.QUALIFICATIONCODE, Name = x.Name, Period = (x.Period ??
"").Trim() }).ToArray();new AjaxResultModel { Data = avail };
}
/// <summary>
/// Список напрвалений отражённых в заявке на добавление
/// </summary>static AjaxResultModel
GetRequestedToAddDirections(this InstitutionsEntities dbContext, int
institutionID)
{<int> temp1;= dbContext.RequestDirection.Where(y =>
y.Activity == "W" && y.Request_ID == institutionID &&
y.Action == "Add").Select(n =>
n.Direction_ID).ToList();<int> temp2 = new List<int>();(int intro
in temp1)
{.Add(Convert.ToInt32(intro));
}avail =.Direction.Where(x => x.DirectionID > 0
&& temp2.Contains(x.DirectionID))
.OrderBy(x => x.Code)
.Select(x => new { ID = x.DirectionID, Code = x.Code, Name
= x.Name, Period = x.PERIOD, x.QUALIFICATIONCODE }).ToArray()
//.Where(x => qualCodes.Contains((x.QUALIFICATIONCODE ??
"").Trim()))
.Select(x => new { ID = x.ID, Code = x.Code,
QualificationCode = x.QUALIFICATIONCODE, Name = x.Name, Period = (x.Period ??
"").Trim() }).ToArray();new AjaxResultModel { Data = avail };
}
/// <summary>
/// Список напрвалений отражённых в заявке на
udalenie
/// </summary>static AjaxResultModel
GetRequestedToDeleteDirections(this InstitutionsEntities dbContext, int
institutionID)
{<int> temp1;= dbContext.RequestDirection.Where(y =>
y.Activity == "W" && y.Request_ID == institutionID &&
y.Action == "Delete").Select(n => n.Direction_ID).ToList();<int>
temp2 = new List<int>();(int intro in temp1)
{.Add(Convert.ToInt32(intro));
}avail =.Direction.Where(x => x.DirectionID > 0
&& temp2.Contains(x.DirectionID))
.OrderBy(x => x.Code)
.Select(x => new { ID = x.DirectionID, Code = x.Code, Name
= x.Name, Period = x.PERIOD, x.QUALIFICATIONCODE }).ToArray()
//.Where(x => qualCodes.Contains((x.QUALIFICATIONCODE ??
"").Trim()))
.Select(x => new { ID = x.ID, Code = x.Code,
QualificationCode = x.QUALIFICATIONCODE, Name = x.Name, Period = (x.Period ??
"").Trim() }).ToArray();new AjaxResultModel { Data = avail };
}static AjaxResultModel GetDeniedDirections(this
InstitutionsEntities dbContext, int institutionID)
{<int> temp1;= dbContext.RequestDirection.Where(y =>
y.Activity == "D" && y.Request_ID == institutionID).Select(n
=> n.Direction_ID).ToList();<int> temp2 = new List<int>();(int
intro in temp1)
{.Add(Convert.ToInt32(intro));
}avail =.Direction.Where(x => x.DirectionID > 0
&& temp2.Contains(x.DirectionID))
.OrderBy(x => x.Code)
.Select(x => new { ID = x.DirectionID, Code = x.Code, Name
= x.Name, Period = x.PERIOD, x.QUALIFICATIONCODE }).ToArray()
//.Where(x => qualCodes.Contains((x.QUALIFICATIONCODE ??
"").Trim()))
.Select(x => new { ID = x.ID, Code = x.Code,
QualificationCode = x.QUALIFICATIONCODE, Name = x.Name, Period = (x.Period ??
"").Trim() }).ToArray();query1 = dbContext.RequestComments(x =>
temp1.Contains(x.RequestDirection.Direction_ID)
&& x.InstitutionID == institutionID
&& x.Commentor == "A")
.OrderByDescending(x => x.Date);<RequestComments>
rlist = new List<RequestComments>();(RequestComments rq in query1)
{(!rlist.Select(x =>
x.DirectionID).Contains(rq.DirectionID))
{.Add(rq);
}
}comment = rlist
.Select(x => new { ID = x.DirectionID, Comment = x.Comment
});new AjaxResultModel { Data = new { Direction = avail, Comment = comment } };
}
/// <summary>
/// Удаляем отклонённые направления в заявке
/// </summary>static AjaxResultModel DeleteDenied(this
InstitutionsEntities dbContext, int instid)
{db = dbContext.RequestDirection.Where(x => x.Request_ID
== instid && x.Activity == "D");(RequestDirection rd in db)
{.RequestDirection.DeleteObject(rd);
}.SaveChanges();new AjaxResultModel();
}
/// <summary>
/// Добавляем новое разрешённое направление в базу
/// </summary>static AjaxResultModel
AddAllowedDirection(this EntrantsEntities dbContext,
AllowedDirectionAddViewModel model, int institutionID)
{
//пришли ошибочные данные, ничего не делаем. Ситуация в нормальной жизни
не должна быть
if (!dbContext.AdmissionItemType.Any(x => x.ItemTypeID ==
model.EducationLevelID && x.ItemLevel == 2))new AjaxResultModel();(var
directionID in (model.DirectionIDs ?? new int[0]))
{
// если нет ещё, то добавляем(!dbContext.AllowedDirections.Any(x
=> x.DirectionID == directionID && x.AdmissionItemTypeID == model.EducationLevelID
&& x.InstitutionID == institutionID))
{ad = new AllowedDirections();.InstitutionID =
institutionID;.AdmissionItemTypeID = (short)model.EducationLevelID;.DirectionID
= directionID;.AllowedDirections.AddObject(ad);
}.SaveChanges();
}new AjaxResultModel();
}
/// <summary>
/// Удаляем разрешённое направление из базы. Проверям что это допустимо.
/// </summary>
public static AjaxResultModel DeleteAllowedDirection(this
EntrantsEntities dbContext, int educationLevelID, int directionID, int institutionID)
//пришли ошибочные данные, ничего не делаем. Ситуация в нормальной жизни
не должна быть
if (!dbContext.AdmissionItemType.Any(x => x.ItemTypeID ==
educationLevelID && x.ItemLevel == 2))new AjaxResultModel();(dbContext.CompetitiveGroupItem.Any(x
=> x.CompetitiveGroup.InstitutionID == institutionID &&
x.DirectionID == directionID
&& x.EducationLevelID == educationLevelID))new
AjaxResultModel("Невозможно удалить направление, так как оно используется
в конкурсных группах.");
var ad = dbContext.AllowedDirections.FirstOrDefault(x =>
x.DirectionID == directionID && x.AdmissionItemTypeID ==
educationLevelID && x.InstitutionID == institutionID);
if (ad != null)
{
// до кучи удаляем объём приёма, он уже больше не нужен (КГ проверили,
нет)
dbContext.AdmissionVolume
.Where(x => x.DirectionID == directionID &&
x.InstitutionID == institutionID && x.AdmissionItemTypeID ==
educationLevelID)
.ToList().ForEach(dbContext.AdmissionVolume.DeleteObject);.AllowedDirections.DeleteObject(ad);.SaveChanges();
}new AjaxResultModel();
}static bool IsInCompetitiveGroup(this EntrantsEntities
dbContext, int institution, int direction, int admtype)
{(dbContext.CompetitiveGroupItem.Any(x =>
x.CompetitiveGroup.InstitutionID == institution && x.DirectionID ==
direction && x.EducationLevelID == (short)admtype))
;
}
Контроллёры - администратор ФИС:
[Authorize(Roles = UserRole.FBDAdmin)]ActionResult ReqList()
{(InstitutionsEntities dbContext = new
InstitutionsEntities())
{View("../Admission/RequestList",
dbContext.InitialFillRequestListViewModel(InstitutionID));
}
}
[Authorize]
[HttpPost]AjaxResultModel MakeEditable(int? institutionid)
{(institutionid == null)new AjaxResultModel("Invalid
value of Institution ID.");(InstitutionsEntities dbContext = new InstitutionsEntities())
{dbContext.AtoU(institutionid ?? 0);
}
}
[Authorize(Roles = UserRole.FBDAdmin)]
[HttpPost]AjaxResultModel GetRequestList(RequestListViewModel
model)
{(var dbContext = new InstitutionsEntities())
{dbContext.GetRequestList(model);
}
}
[Authorize(Roles = UserRole.FBDAdmin)]
[HttpPost]AjaxResultModel GetRequest(int? institutionid)
{(var dbContext = new InstitutionsEntities())
{dbContext.FillRequestList(institutionid ?? 0);
}
}
[Authorize(Roles = UserRole.FBDAdmin)]
[HttpPost]AjaxResultModel AddDirection(int? did, int? inid,
int? adtype)
{(var dbContext = new InstitutionsEntities())
{dbContext.AcceptRequest(did ?? 0, inid ?? 0, adtype ?? 0);
}
}
[Authorize(Roles = UserRole.FBDAdmin)]
[HttpPost]AjaxResultModel DenyRequest(int? did,string comment,
int? inid)
{(var dbContext = new InstitutionsEntities())
{dbContext.DenyRequestAdmin(did ?? 0, inid ?? 0, comment);
}
}ActionResult Index()
{View();
}
Функции из файлов расширения:static RequestListViewModel
InitialFillRequestListViewModel(this InstitutionsEntities dbContext, int
currentInstitutionID)
{model = new RequestListViewModel();.CurrentInstitutionID =
currentInstitutionID;model;
}static AjaxResultModel FillRequestList(this
InstitutionsEntities dbContext, int InstID)
{query = dbContext.RequestDirection.Where(x =>
x.Request_ID == InstID && x.Activity == "W").Select(x =>
x.Direction_ID);current = dbContext.Direction.Where(x =>
query.Contains(x.DirectionID)).OrderBy(x => x.DirectionID)
.Select(x => new { ID = x.DirectionID, Code = x.Code, Name
= x.Name, Period = x.PERIOD, x.QUALIFICATIONCODE}).ToArray()
.Select(x => new { ID = x.ID, Code = x.Code,
QualificationCode = x.QUALIFICATIONCODE, Name = x.Name, Period = (x.Period ??
"").Trim() }).ToArray();;query1 = dbContext.RequestComments.Include(x
=> x.RequestDirection).Where(x => x.InstitutionID == InstID &&
x.Commentor == "U").OrderByDescending(x =>
x.Date);<RequestComments> rlist = new
List<RequestComments>();(RequestComments rq in query1)
{(!rlist.Select(x =>
x.DirectionID).Contains(rq.DirectionID))
{.Add(rq);
}
}(RequestDirection rd in dbContext.RequestDirection.Where(x
=> x.Request_ID == InstID && x.Activity == "W"))
{.Activity = "A";
}.SaveChanges();rt = new RequestThread(InstID);new
AjaxResultModel { Data = new { Request = current, Comment = rlist.OrderBy(x
=> x.DirectionID).Select(x => new { DirectionID = x.DirectionID, Comment
= x.Comment, Action = x.RequestDirection.Action, admissionType =
x.RequestDirection.AdmissionItemType}) } };
}static AjaxResultModel GetInstitutionList(this
InstitutionsEntities dbContext, InstitutionListViewModel model)
{query = dbContext.Institution
.Include(x => x.RegionType)
.Include(x => x.FormOfLaw)
.Include(x => x.UserPolicy);
{(!String.IsNullOrEmpty(model.Filter.ShortName))=
query.Where(x =>
x.BriefName.Contains(model.Filter.ShortName));(!String.IsNullOrEmpty(model.Filter.FullName))=
query.Where(x =>
x.FullName.Contains(model.Filter.FullName));(!String.IsNullOrEmpty(model.Filter.Owner))=
query.Where(x =>
x.OwnerDepartment.Contains(model.Filter.Owner));(model.Filter.InstitutionTypeID
> 0)= query.Where(x => x.InstitutionTypeID ==
model.Filter.InstitutionTypeID);(model.Filter.FormOfLawID > 0)=
query.Where(x => x.FormOfLawID == model.Filter.FormOfLawID);(model.Filter.RegionID
> 0)= query.Where(x => x.RegionID ==
model.Filter.RegionID);(!String.IsNullOrEmpty(model.Filter.OGRN))=
query.Where(x => x.OGRN ==
model.Filter.OGRN);(!String.IsNullOrEmpty(model.Filter.INN))= query.Where(x
=> x.OGRN == model.Filter.INN);
}pageNumber = model.PageNumber;(!pageNumber.HasValue ||
pageNumber < 0) pageNumber = 0;totalCount =
query.Count();.TotalItemFilteredCount = totalCount;.TotalPageCount =
((Math.Max(totalCount, 1) - 1) / InstitutionListPageSize) + 1;filtQuery = query
.Skip(pageNumber.Value * InstitutionListPageSize)
.Take(InstitutionListPageSize);.Institutions =
filtQuery.ToArray().Select(x => new InstitutionListViewModel.InstitutionData
{= x.InstitutionID,= x.BriefName ?? x.FullName ??
"",= x.FullName ?? "",= x.InstitutionTypeID == 1 ? "ВУЗ" : (x.InstitutionTypeID == 2 ?
"ССУЗ" : ""),=
x.FormOfLaw != null ? x.FormOfLaw.Name : "",= x.OwnerDepartment ??
"",= x.RegionType != null ? x.RegionType.Name : "",=
x.UserPolicy.Count()
}).ToArray();new AjaxResultModel { Data = model };
}
/// <summary>
/// Возвращаем интституты и их заявки
/// </summary>static AjaxResultModel
GetRequestList(this InstitutionsEntities dbContext, RequestListViewModel model)
{
//var query = from request in dbContext.RequestDirection
// join institute in dbContext.Institution on
request.Request_ID equals institute.InstitutionID
// select new { InstId = institute.InstitutionID, /*Date =
request.ChangeDate,*/ name = institute.FullName, /*DirId = request.Direction_ID
*/};
//query = query.Distinct();query2 =
dbContext.RequestDirection.Where(x => x.Activity == "W").Include(x
=> x.Institution);<int> query1 = query2.Select(x =>
x.Institution.InstitutionID).Distinct().ToList();<RequestDirection> queryL
= new List<RequestDirection>();(RequestDirection q in query2)
{(query1.Contains(q.Request_ID))
{.Add(q);.Remove(q.Institution.InstitutionID);
}
}query = queryL.AsEnumerable();
//sorting((model.SortID ?? 0) == 0).SortID = 1;(model.SortID
== 1) query = query.OrderBy(x => x.Institution.FullName);(model.SortID ==
-1) query = query.OrderByDescending(x =>
x.Institution.FullName);(model.SortID == 3) query = query.OrderBy(x =>
x.ChangeDate);(model.SortID == -3) query = query.OrderByDescending(x =>
x.ChangeDate);(model.SortID == 2) query = query.OrderBy(x =>
dbContext.RequestDirection.Where(z => z.Institution.InstitutionID ==
x.Request_ID && z.Activity == "W").Count());(model.SortID ==
-2) query = query.OrderByDescending(x => dbContext.RequestDirection.Where(z
=> z.Institution.InstitutionID == x.Request_ID && z.Activity ==
"W").Count());.TotalItemCount = query.Count();
/*(model.Filter != null)
{(!String.IsNullOrEmpty(model.Filter.ShortName))=
query.Where(x =>
x.BriefName.Contains(model.Filter.ShortName));(!String.IsNullOrEmpty(model.Filter.FullName))=
query.Where(x =>
x.FullName.Contains(model.Filter.FullName));(!String.IsNullOrEmpty(model.Filter.Owner))=
query.Where(x =>
x.OwnerDepartment.Contains(model.Filter.Owner));(model.Filter.InstitutionTypeID
> 0)= query.Where(x => x.InstitutionTypeID ==
model.Filter.InstitutionTypeID);(model.Filter.FormOfLawID > 0)=
query.Where(x => x.FormOfLawID ==
model.Filter.FormOfLawID);(model.Filter.RegionID > 0)= query.Where(x =>
x.RegionID == model.Filter.RegionID);(!String.IsNullOrEmpty(model.Filter.OGRN))=
query.Where(x => x.OGRN ==
model.Filter.OGRN);(!String.IsNullOrEmpty(model.Filter.INN))= query.Where(x
=> x.OGRN == model.Filter.INN);
}
*/pageNumber = model.PageNumber;(!pageNumber.HasValue ||
pageNumber < 0) pageNumber = 0;totalCount = query.Count();.TotalItemFilteredCount
= totalCount;.TotalPageCount = ((Math.Max(totalCount, 1) - 1) /
InstitutionListPageSize) + 1;filtQuery = query
.Skip(pageNumber.Value * InstitutionListPageSize)
.Take(InstitutionListPageSize);.Institutions =
filtQuery.ToArray().Select(x => new RequestListViewModel.InstitutionData
{= x.Request_ID,= x.Institution.FullName,=
dbContext.RequestDirection.Where(z => z.Institution.InstitutionID ==
x.Request_ID && z.Activity == "W").Count(),=
x.ChangeDate.ToString()
}).ToArray();new AjaxResultModel { Data = model };
}static AjaxResultModel DenyRequestAdmin(this
InstitutionsEntities dbContext, int DirectionID, int InstitutionID, string
Comment)
{(DirectionID * InstitutionID == 0) return new
AjaxResultModel("Data sending error. Try again later.");rq = dbContext.RequestDirection.Where(x
=> x.Direction_ID == DirectionID && x.Request_ID ==
InstitutionID).Single();.Activity = "D";rc =
Model.Institutions.RequestComments.CreateRequestComments(dbContext.RequestComments.Count()
+ 1, "A", DirectionID, InstitutionID);.Comment =
Comment;.AddToRequestComments(rc);.SaveChanges();new AjaxResultModel();
}static AjaxResultModel AcceptRequest(this
InstitutionsEntities dbContext, int DirID, int InstId, int adType)
{rd = dbContext.RequestDirection.Where(x => x.Direction_ID
== DirID && x.Request_ID == InstId && x.AdmissionItemType ==
adType).Single();(EntrantsEntities dbContextE = new EntrantsEntities())
{(rd.Action == "Add")
{.Model.Entrants.AllowedDirections ad = new
GVUZ.Model.Entrants.AllowedDirections();.InstitutionID =
InstId;.AdmissionItemTypeID = (short)adType;.DirectionID =
DirID;.AllowedDirections.AddObject(ad);
}(rd.Action == "Delete")
{.Model.Entrants.AllowedDirections ad =
dbContextE.AllowedDirections.Where(x =>.InstitutionID == InstId
&&.AdmissionItemTypeID == (short)adType &&.DirectionID ==
DirID).First();.AllowedDirections.DeleteObject(ad);
}.SaveChanges();
}.RequestDirection.DeleteObject(rd);.SaveChanges();new
AjaxResultModel();
}static AjaxResultModel AtoU(this InstitutionsEntities
dbContext, int instid)
{(RequestDirection rd in dbContext.RequestDirection.Where(x
=> x.Activity == "A" && x.Request_ID == instid))
{.Activity = "W";
}.SaveChanges();new AjaxResultModel();
}RequestThread
{.Threading.Thread thread;dbContext;RequestThread(int instID)
{= new System.Threading.Thread(this.func);.Start(instID);=
new InstitutionsEntities();
}func(object instID)
{id =
Convert.ToInt32(instID);.Threading.Thread.Sleep(900000);(RequestDirection rd in
dbContext.RequestDirection.Where(x => x.Activity == "A" &&
x.Request_ID == id))
{.Activity = "W";
}.SaveChanges();
}
}