Способы выборки объектов в Fluent NHibernate
В Fluent NHibernate существует 4 способа выборки объектов:
- Native SQL;
- запросы по критерию;
- запросы по образцу;
- язык запросов HQL (Hibernate Query Language).
Рассмотрим каждый из способов.
Запросы Native SQL
Механизм запрос Native SQL позволяет выполнять запросы, написанные на обычном языке SQL. В метод просто передается запрос в виде текстовой строки.
Рассмотрим пример, в котором с базы данных выбирается набор объектов класса студент:
var list = session.CreateSQLQuery(
"SELECT Students.* FROM Students")
.AddEntity("Student", typeof(Student))
.List<Student>();
Как видно из примера, запрос на выборку просто передается в метод CreateSQLQuery сессии NHibernate. Запрос может быть любой сложности но при написании запросов с использованием Native SQL необходимо задуматься, а какого типа будут объекты в возвращаемой коллекции.
Запросы по критерию
Вторым и очень удобным способом выборки объектов с базы является запрос по критерию.
Рассмотрим пример, в котором с базы выбираются все те же студенты по разным признакам.
В первом критерии выбираются студенты мужского пола:
ICriteria criteria1 = session.CreateCriteria(typeof(Student))
.Add(Expression.Eq("Sex", 'M'))
.SetMaxResults(10);
list = criteria1.List<Student>();
Во втором примере выбираются студенты, у которых имя начинается на букву К, список упорядочен по фамилии по возрастанию и по году рождения по убыванию:
ICriteria criteria2 = session.CreateCriteria(typeof(Student))
.Add(Expression.Like("FirstName", "K%"))
.AddOrder(Order.Asc("LastName"))
.AddOrder(Order.Desc("Year"));
list = criteria2.List<Student>();
В третьем примере выбирается список студентов, у которых год рождения находится между 1993 и 1994 годами:
ICriteria criteria3 = session.CreateCriteria(typeof(Student))
.Add(Expression.Between("Year", 1993, 1994));
list = criteria3.List<Student>();
Более детально с запросами по критерию можно ознакомиться в книге NHibernate in Action.
Запросы по образцу
Запросы по образцу основаны на создании объекта образца, который похож на объекты, которые необходимо выбрать с базы данных.
Рассмотрим пример запроса по образцу для студента. В примере создается объект шаблон с заполненными полями пола и года рождения. Потом на основании этого объекта создается пример, который потом передается в критерий.
//Создание объекта образца
Student s1 = new Student();
s.Sex = 'M';
s.Year = 1994;
//Создание примера
Example example = Example.Create(s1)
.ExcludeZeroes()
.ExcludeProperty("Year")
.IgnoreCase()
.EnableLike();
//Передача примера в качестве параметра в критерий
ICriteria criteria5 = session.CreateCriteria(typeof(Student))
.Add(example);
list = criteria5.List<Student>();
Запросы HQL
Кроме трех выше описанных способов существует еще один очень удобный способ выборки объектов с базы данных – язык запросов HQL, который позволяет полностью абстрагироваться от реляционных баз данных и заставить программиста мыслить исключительно объектами домена.
Рассмотрим пару примеров запросов на HQL.
В первом примере выбираются все студенты с именем Кристина:
IQuery query = session.CreateQuery("from Student as stud where stud.FirstName = :Name");
query.SetAnsiString("Name", "Kristina");
list = query.List<Student>();
Во втором примере выбираются фамилии всех студентов, у которых имя группы похоже на «KI-»:
IQuery query1 = session.CreateQuery("select st.LastName from Student as st inner join st.Group as gr where gr.GroupName like 'KI-%'");
IList<String> list1 = query1.List<String>();
Более подробно с запросами HQL можно ознакомиться в книге NHibernate in Action.
Порядок выполнения работы
В данном порядке выполнения лабораторной работы будет разработано приложение, которое будет работать с данными с базы данных (отображать, добавлять удалять, редактировать данные). Доступ к базе будет осуществляться с применением технологии ORM (object relation mapping) Fluent NHibernate. В качестве СУБД был выбран PostgreSQL. Предметная область будет состоять из двух объектов: «Группа» и «Студент», которые состоят в отношении один ко многим. Старайтесь разобраться с кодом, который копируете в проект.
Этап I - Подготовка
1. Установите PostgreSQL. Создайте базу данных university.
2. Создайте новое приложение Windows Forms.
3. Создайте каталоги domain, mapping и dao.
4. Добавьте в каталог с проектом библиотеки для работы с СУБД PostgreSQL, библиотеки NHibernate и библиотеки Fluent NHibernate. Данные библиотеки можно скачать по ссылкам:
Драйвер к postgreSQL | http://www.postgresql.org/ |
Библиотеки NHibernate | http://sourceforge.net/projects/nhibernate/ |
Библиотеки Fluent NHibernate | http://fluentnhibernate.org/ |
В данном проекте были использованы архивы:
- Npgsql2.0.10-bin-ms.net.zip
- NHibernate-2.1.2.GA-bin.zip
- fluentnhibernate-1.1.zip
Список всех необходимых библиотек приведен ниже:
Npgsql.dll |
Mono.Security.dll |
NHibernate.dll |
Antlr3.Runtime.dll |
Iesi.Collections.dll |
log4net.dll |
Castle.DynamicProxy2.dll |
Castle.Core.dll |
NHibernate.ByteCode.Castle.dll |
FluentNHibernate.dll |
Подключите библиотеки Npgsql.dll, NHibernate.dll, FluentNHibernate.dll и NHibernate.ByteCode.Castle к проекту (нажмите правой кнопкой на «Ссылки» в дереве объектов потом на «Добавить ссылку…», перейдите на закладку «Обзор», выберите необходимые файлы).
Теперь все готово для создания слоя доступа к данным DAO. В лабораторной работе можно использовать NHibernate и Fluent Hibernate более поздних версий, например NHibernate 3.
Этап II – Создание слоя доступа к данным (DAO)
Будьте внимательны при разработке слоя доступа к данным, поскольку он будет использоваться в следующих лабораторных работах.
5. В каталоге domain создайте три класса-домена EntityBase, Group и Student. Тексты классов приведены ниже:
namespace lab4.domain
{
//Класс базовой сущности
public abstract class EntityBase
{
public virtual long Id { get; set; }
}
}
using System.Collections.Generic;
namespace lab4.domain
{
//Сущность группы
public class Group:EntityBase
{
private IList<Student> studentList = new List<Student>();
public virtual string GroupName { get; set; }
public virtual string CuratorName { get; set; }
public virtual string HeadmanName { get; set; }
public virtual IList<Student> StudentList
{
get { return studentList; }
set { studentList = value; }
}
}
}
namespace lab4.domain
{
//Сущность студента
public class Student:EntityBase
{
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public virtual char Sex { get; set; }
public virtual int Year { get; set; }
public virtual Group Group { get; set; }
}
}
6. Создайте в каталоге dao интерфейс IGenericDAO, в котором описаны все необходимые для слоя доступа к данным методы. Набор методов определяется на этапе проектирования в зависимости от потребностей системы. Интерфейс IGenericDAO приведен ниже:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace lab4.dao
{
public interface IGenericDAO<T>
{
void SaveOrUpdate(T item);
T GetById(long id);
List<T> GetAll();
void Delete(T item);
}
}
7. Помимо стандартного набора методов, dao каждого объекта может иметь свой собственный дополнительный список методов. Так, например, для объекта-группы таким методом является getAllStudentOfGroup (получить список студентов заданной группы). Поэтому для каждого объекта предметной области необходимо создать свои интерфейсы, которые расширяют IGenericDAO. Ниже приведены интерфейсы IGroupDAO и IStudentDAO:
using lab4.domain;
using System.Collections.Generic;
namespace lab4.dao
{
public interface IGroupDAO:IGenericDAO<Group>
{
Group getGroupByName(string groupName);
IList<Student> getAllStudentOfGroup(string groupName);
void delGroupByName(string groupName);
}
}
using lab4.domain;
namespace lab4.dao
{
public interface IStudentDAO:IGenericDAO<Student>
{
Student getStudentByGroupFirstNameAndLastName(
string groupName, string firstName, string LastName);
}
}
8. Создайте в каталоге dao абстрактную фабрику, которая будет возвращать DAO для каждой сущности:
namespace lab4.dao
{
abstract public class DAOFactory
{
public abstract IStudentDAO getStudentDAO();
public abstract IGroupDAO getGroupDAO();
}
}
9. Теперь необходимо создать реализации интерфейсов IGenericDAO, IGroupDAO, IStudentDAO и абстрактной фабрики для Fluent NHibernate. Ниже приведена реализация IGenericDAO:
using System;
using System.Collections.Generic;
using NHibernate;
namespace lab4.dao
{
public class GenericDAO<T>:IGenericDAO<T>
{
protected ISession session;
public GenericDAO() { }
public GenericDAO(ISession session)
{
this.session = session;
}
public void SaveOrUpdate(T item)
{
ITransaction transaction = session.BeginTransaction();
session.SaveOrUpdate(item);
transaction.Commit();
}
public T GetById(long id)
{
return session.Get<T>(id);
}
public List<T> GetAll()
{
return new List<T>(session.CreateCriteria(typeof(T)).List<T>());
}
public void Delete(T item)
{
ITransaction transaction = session.BeginTransaction();
session.Delete(item);
transaction.Commit();
}
}
}
10. Создайте в каталоге dao реализацию интерфейсов IGroupDAO, IStudentDAO:
using lab4.domain;
using NHibernate;
using System.Collections.Generic;
using NHibernate.Criterion;
namespace lab4.dao
{
public class GroupDAO:GenericDAO<Group>, IGroupDAO
{
public GroupDAO(ISession session) : base(session) { }
public Group getGroupByName(string groupName)
{
Group group = new Group();
group.GroupName = groupName;
ICriteria criteria = session.CreateCriteria(typeof(Group))
.Add(Example.Create(group));
IList<Group> list = criteria.List<Group>();
group = list[0];
return group;
}
public IList<Student> getAllStudentOfGroup(string groupName)
{
var list = session.CreateSQLQuery(
"SELECT Students.* FROM Students JOIN Groups" +
" ON Students.GroupId = Groups.Id" +
" WHERE Groups.GroupName='" + groupName + "'")
.AddEntity("Student", typeof(Student))
.List<Student>();
return list;
}
public void delGroupByName(string groupName)
{
Group group = getGroupByName(groupName);
Delete(group);
}
}
}
using lab4.domain;
using NHibernate;
namespace lab4.dao
{
public class StudentDAO:GenericDAO<Student>, IStudentDAO
{
public StudentDAO(ISession session): base(session) { }
public Student getStudentByGroupFirstNameAndLastName(
string groupName, string firstName, string lastName)
{
var list = session.CreateSQLQuery(
"SELECT Students.* FROM Students JOIN Groups" +
" ON Students.GroupId = Groups.Id" +
" WHERE Groups.GroupName='" + groupName + "'" +
" and Students.FirstName='" + firstName + "'" +
" and Students.LastName='" + lastName + "'")
.AddEntity("Student", typeof(Student))
.List<Student>();
Student student = list[0];
return student;
}
}
}
11. Создайте реализацию абстрактной фабрики NHibernateDAOFactory:
using System;
using FluentNHibernate;
using NHibernate;
namespace lab4.dao
{
public class NHibernateDAOFactory:DAOFactory
{
/** NHibernate sessionFactory */
protected ISession session = null;
public NHibernateDAOFactory(ISession session)
{
this.session = session;
}
public override IStudentDAO getStudentDAO()
{
return new StudentDAO(session);
}
public override IGroupDAO getGroupDAO()
{
return new GroupDAO(session);
}
}
}
12. Создадим классы проецирования объектов предметной области на базу данных. В соответствии c mapping-классами в базе данных будут создаваться таблицы и связи между ними. При использовании NHibernate вместо Fluent NHibernate вместо классов используются XML-файлы. Mapping-классы для объектов «Группа» и «Студент».
using FluentNHibernate.Mapping;
using lab4.domain;
namespace lab4.mapping
{
public class GroupMap:ClassMap<Group>
{
public GroupMap()
{
Table("Groups");
Id(x => x.Id).GeneratedBy.Native();
Map(x => x.GroupName);
Map(x => x.CuratorName);
Map(x => x.HeadmanName);
HasMany(x => x.StudentList)
.Inverse()
.Cascade.All()
.KeyColumn("GroupId");
}
}
}
using FluentNHibernate.Mapping;
using lab4.domain;
namespace lab4.mapping
{
public class StudentMap:ClassMap<Student>
{
public StudentMap()
{
Table("Students");
Id(x => x.Id).GeneratedBy.Native();
Map(x => x.FirstName);
Map(x => x.LastName);
Map(x => x.Sex);
Map(x => x.Year);
References(x => x.Group, "GroupId");
}
}
}
Слой доступа к данным реализован.
Этап III – Реализация слоя отображения
Слой отображения в данной лабораторной работе будет реализован с использованием Windows Forms (толстый клиент). В следующей лабораторной работе слой отображения будет реализован с использованием технологии ASP.NET как тонкий клиент.
13. Создайте три дополнительные формы. Одна будет использоваться для ввода настроек подключения, вторая - для добавления и изменения группы, третья – для добавления и изменения студента.
14. На главной форме разметите компонент MenuStrip, добавьте к нему пункт меню «Источник данных», а к пункту «Источник данных» пункты «Подключение к базе» и «Отключение от базы», создайте обработчики нажатия на эти два пункта меню.
15. Установите на форму компонент SplitConteiner для того, чтобы разделить рабочую область формы на две части.
16. Установите с левую и правую части компонент GoupBox. Установите у левого GoupBox свойство Text в значение «Группы», а у правого свойство Text в значение – «Студенты», установите у обоих GoupBox свойство Dock в значение Fill.
17. Разместите на левом и на правом GoupBox компоненты DataGridView. Установите у них свойство Dock в значение Fill. Левый DataGridView будет использоваться для отображения списка групп, а правый для отображения списка студентов в группе. Настройте каждый из DataGridView следующим образом: ReadOnly – True, MultiSelect – False, RowHeadersVisible – False, SelectionMode – FullRowSelect, AllowUserToAddRows - False.
18. Добавьте в первый DataGridView колонки «Название группы», «ФИО куратора», «ФИО старосты», а во второй добавьте колонки «Имя», «Фамилия», «Пол», «Год рождения». Добавить колонки можно с помощью свойства Columns. В конструкторе колонок необходимо внимательно следить за свойством Name колонки, через которое потом происходит обращение к колонке из программы.
19. Добавьте два компонента ContextMenuStrip, свяжите одно контекстное меню с левым DataGridView, а другое с правым DataGridView через свойство ContextMenuStrip. Добавьте в каждом меню три пункта «Добавить», «Удалить», «Заменить», к каждому пункту меню добавьте обработчик на нажатие.
20. Теперь необходимо реализовать функцию подключения приложения к базе данных. Связывать приложение с базой данных будет сессия NHibernate. Разместите на второй форме (Form2) пять компонентов TextBox, каждый TextBox можно подписать с использованием компонента Label. Первый TextBox будет использоваться для ввода имени хоста, второй – для ввода порта, третий – для ввода имени базы данных, четвертый – для ввода имени пользователя, а пятый – для ввода пароля. На форме также следует поместить кнопку и назвать ее, например, «Подключиться».
Конечный результат проектирования формы подключения к базе представлен на рисунке 4.1.
Рисунок 4.1 – Форма подключения к базе
21. Каждая форма должна иметь доступ к родительской форме (Form1), а также к сессии (ISession). Откройте форму Form2 с использованием редактора CSharp. Добавьте над конструктором формы поля:
private ISessionFactory factory;
//Ссылка на сессию
private ISession session;
//Ссылка на родительскую форму
private Form1 perent;
22. Добавьте метод по установке поля perent:
public void setPerent(Form1 perent)
{
this.perent = perent;
}
23. Добавьте методы по открытию сессии:
//Метод открытия сессии
private ISession openSession(String host, int port, String database,
String user, String passwd)
{
ISession session = null;
//Получение ссылки на текущую сборку
Assembly mappingsAssemly = Assembly.GetExecutingAssembly();
if (factory == null)
{
//Конфигурирование фабрики сессий
factory = Fluently.Configure()
.Database(PostgreSQLConfiguration
.PostgreSQL82.ConnectionString(c => c
.Host(host)
.Port(5432)
.Database(database)
.Username(user)
.Password(passwd)))
.Mappings(m => m.FluentMappings
.AddFromAssembly(mappingsAssemly))
.ExposeConfiguration(BuildSchema)
.BuildSessionFactory();
}
//Открытие сессии
session = factory.OpenSession();
return session;
}
//Метод для автоматического создания таблиц в базе данных
private static void BuildSchema(Configuration config)
{
new SchemaExport(config).Create(false, true);
}
24. Добавьте обработчик нажатия на кнопку «Подключиться»:
private void button1_Click(object sender, EventArgs e)
{
session = openSession(this.textBox1.Text,
Convert.ToInt32(this.textBox2.Text),
this.textBox3.Text, this.textBox4.Text, this.textBox5.Text);
//Скрытие формы
this.Visible = false;
//Передача открытой сессии открытой форме
perent.setSession(session);
//Вывод в таблицу всех групп
perent.fillDataGridView1();
}
25. Теперь необходимо добавить функции по подключению и отключении приложения от базы данных. Откройте Form1 в режиме редактора CSharp. Добавьте над конструктором формы поля:
private ISession session;
private Form2 form2 = null;
private Form3 form3 = null;
private Form4 form4 = null;
Поля form3, и form4 понадобятся для форм добавления и редактирования групп и студентов.
Также необходимо добавить метод setSession(), чтобы установки соединения могла передасть сессию главной форме:
public void setSession(ISession session)
{
this.session = session;
}
Для удобства обращения к форме добавьте метод по созданию и инициализации формы:
private Form2 getForm2()
{
if (form2 == null)
{
form2 = new Form2();
}
form2.setPerent(this);
return form2;
}
26. Заполните обработчики нажатия на пункты меню «Подключение к базе», «Отключиться от базы»:
private void присоединитьсяКБазеToolStripMenuItem_Click(
object sender, EventArgs e)
{
getForm2().Visible = true;
}
private void отключитьсяОтБазыToolStripMenuItem_Click(
object sender, EventArgs e)
{
session.Close();
dataGridView1.Rows.Clear();
dataGridView2.Rows.Clear();
}
27. Добавьте методы по заполнению компонентов DataGridView данными о группах и студентах:
//Метод по заполнению dataGridView1
public void fillDataGridView1()
{
dataGridView1.Rows.Clear();
//Создание экземпляра фабрики NHibernate
DAOFactory dao = new NHibernateDAOFactory(session);
//Получение dao группы
IGroupDAO groupDAO = dao.getGroupDAO();
//Получение коллекции групп с базы
List<Group> groupList = groupDAO.GetAll();
//Вывод всех групп в таблицу
foreach (Group g in groupList)
{
DataGridViewRow row = new DataGridViewRow();
DataGridViewTextBoxCell cell1 = new DataGridViewTextBoxCell();
DataGridViewTextBoxCell cell2 = new DataGridViewTextBoxCell();
DataGridViewTextBoxCell cell3 = new DataGridViewTextBoxCell();
cell1.ValueType = typeof(string);
cell1.Value = g.GroupName;
cell2.ValueType = typeof(string);
cell2.Value = g.CuratorName;
cell3.ValueType = typeof(string);
cell3.Value = g.HeadmanName;
row.Cells.Add(cell1);
row.Cells.Add(cell2);
row.Cells.Add(cell3);
dataGridView1.Rows.Add(row);
}
}
//Вывод всех студентов заданной группы в dataGridView2
public void fillDataGridView2(string key)
{
dataGridView2.Rows.Clear();
//Создание фабрики NHibernate
DAOFactory dao = new NHibernateDAOFactory(session);
//Получение dao группы
IGroupDAO groupDAO = dao.getGroupDAO();
//Получение студентов заданной группы
IList<Student> studentList = groupDAO.getAllStudentOfGroup(key);
foreach (Student s in studentList)
{
DataGridViewRow row = new DataGridViewRow();
DataGridViewTextBoxCell cell1 = new DataGridViewTextBoxCell();
DataGridViewTextBoxCell cell2 = new DataGridViewTextBoxCell();
DataGridViewTextBoxCell cell3 = new DataGridViewTextBoxCell();
DataGridViewTextBoxCell cell4 = new DataGridViewTextBoxCell();
cell1.ValueType = typeof(string);
cell1.Value = s.FirstName;
System.Console.WriteLine(s.FirstName + "\n");
cell2.ValueType = typeof(string);
cell2.Value = s.LastName;
cell3.ValueType = typeof(string);
cell3.Value = s.Sex;
cell4.ValueType = typeof(string);
cell4.Value = s.Year;
row.Cells.Add(cell1);
row.Cells.Add(cell2);
row.Cells.Add(cell3);
row.Cells.Add(cell4);
dataGridView2.Rows.Add(row);
}
}
28. Приступим к реализации функций добавления, удаления и замены группы. Откройте Form3 в режиме конструктора, добавьте три компонента TextBox (поле ввода). Первое поле ввода будет использоваться для ввода названия группы, второе – для ввода ФИО куратора, третье – для ввода ФИО старосты. Поля ввода можно подписать компонентом Label. Добавьте две кнопки: «Добавить» и «Заменить». Результат проектирования формы группы представлен на рисунке 4.2.
Рисунок 4.2 – Форма добавления и замены группы
29. Откройте Form3 в режиме конструктора CSharp. Добавьте над конструктором класса поля:
private ISession session;
private Form1 perent;
private string key;
Первое поле хранит в себе ссылку на сессию, второе поле – ссылку на главную форму, а третье – ключ, который нам необходим будет при замене группы. Для установки значений этих полей добавьте методы:
public void setPerent(Form1 perent)
{
this.perent = perent;
}
public void setSession(ISession session)
{
this.session = session;
}
public void setKey(string key)
{
this.key = key;
}
30. Для того чтобы получить доступ к полям ввода и кнопкам с главной формы добавьте следующие set-методы:
public void setTextBox1Text(string text)
{
this.textBox1.Text = text;
}
public void setTextBox2Text(string text)
{
this.textBox2.Text = text;
}
public void setTextBox3Text(string text)
{
this.textBox3.Text = text;
}
public void setButton1Visible(bool visible)
{
this.button1.Visible = visible;
}
public void setButton2Visible(bool visible)
{
this.button2.Visible = visible;
}
31. Добавьте обработчики нажатия кнопок «Добавить» и «Заменить»:
//Обработчик на Добавить
private void button1_Click(object sender, EventArgs e)
{
DAOFactory dao = new NHibernateDAOFactory(session);
IGroupDAO groupDAO = dao.getGroupDAO();
Group group = new Group();
group.GroupName = textBox1.Text;
group.HeadmanName = textBox2.Text;
group.CuratorName = textBox3.Text;
groupDAO.SaveOrUpdate(group);
perent.fillDataGridView1();
this.Visible = false;
}
//Обработчик на Заменить
private void button2_Click(object sender, EventArgs e)
{
DAOFactory dao = new NHibernateDAOFactory(session);
IGroupDAO groupDAO = dao.getGroupDAO();
Group group = groupDAO.getGroupByName(key);
group.GroupName = textBox1.Text;
group.CuratorName = textBox2.Text;
group.HeadmanName = textBox3.Text;
groupDAO.SaveOrUpdate(group);
this.Visible = false;
perent.fillDataGridView1();
}
32. Откройте Form1 в редакторе кода CSharp. Для удобства работы с Form3 добавьте метод:
private Form3 getForm3()
{
if (form3 == null)
{
form3 = new Form3();
}
form3.setSession(session);
form3.setPerent(this);
return form3;
}
33. Заполните обработчики «Добавить», «Удалить», «Заменить» для контекстного меню группы:
//Нажатие на "Добавить" в контекстном меню группы
private void добавитьToolStripMenuItem_Click(object sender, EventArgs e)
{
getForm3().Visible = true;
getForm3().setTextBox1Text("");
getForm3().setTextBox2Text("");
getForm3().setTextBox3Text("");
getForm3().setButton1Visible(true);
getForm3().setButton2Visible(false);
}
//Нажатие на "Удалить" в контекстном меню группы
private void удалитьToolStripMenuItem_Click(object sender, EventArgs e)
{
DAOFactory dao = new NHibernateDAOFactory(session);
IGroupDAO groupDAO = dao.getGroupDAO();
int selectedRow = dataGridView1.SelectedCells[0].RowIndex;
string key = (string)dataGridView1.Rows[selectedRow].Cells[0].Value;
DialogResult dr = MessageBox.Show("Удалить студента?", "",
MessageBoxButtons.YesNo);
if (dr == DialogResult.Yes)
{
try
{
groupDAO.delGroupByName(key);
this.fillDataGridView1();
}
catch (Exception)
{
}
}
}
//Нажатие на "Заменить" в контекстном меню группы
private void изменитьToolStripMenuItem_Click(object sender, EventArgs e)
{
int selectedRow = dataGridView1.SelectedCells[0].RowIndex;
string key = (string)dataGridView1.Rows[selectedRow].Cells[0].Value;
DAOFactory dao = new NHibernateDAOFactory(session);
IGroupDAO groupDAO = dao.getGroupDAO();
Group group = groupDAO.getGroupByName(key);
getForm3().Visible = true;
getForm3().setKey(key);
getForm3().setTextBox1Text(group.GroupName);
getForm3().setTextBox2Text(group.CuratorName);
getForm3().setTextBox3Text(group.HeadmanName);
getForm3().setButton1Visible(false);
getForm3().setButton2Visible(true);
}
34. Для того чтобы при нажатии на строчку DataGridView для группы в DataGridView для студентов отображался список студентов выделенной группы, добавьте обработчик нажатия на строчку DataGridView:
//Обработчик нажатия на строчку DataGridView группы
private void dataGridView1_CellClick(
object sender, DataGridViewCellEventArgs e)
{
int selectedRow = dataGridView1.SelectedCells[0].RowIndex;
string key = (string)dataGridView1.Rows[selectedRow].Cells[0].Value;
fillDataGridView2(key);
}
35. Приступим к реализации функций добавления, удаления и замены студента. Откройте Form4 в режиме конструктора. Добавьте 4 компонента TextBox (поля ввода). Первое поле будет использоваться для ввода имени студента, второе – для ввода фамилии студента, третье – для ввода пола студента, четвертое – для ввода года рождения студента. Каждое поле ввода целесообразно подписать с использованием компонента Label. Добавьте на форму кнопки «Добавить» и «Заменить». Результат проектирования формы студента представлен на рисунке 4.3
Рисунок 4.3 – Форма добавления и замены студента
36. Откройте Form4 в режиме редактора CSharp. Добавьте над конструктором класса формы поля:
private ISession session;
private Form1 perent;
private string key1;
private string key2;
private string key3;
Поле key1 содержит название группы, поле key2 содержит имя студента, поле key3 содержит фамилию студента.
37. Добавьте set-методы по установке вышеописанных переменных:
public void setSession(ISession session)
{
this.session = session;
}
public void setPerent(Form1 perent)
{
this.perent = perent;
}
public void setKey1(string key1)
{
this.key1 = key1;
}
public void setKey2(string key2)
{
this.key2 = key2;
}
public void setKey3(string key3)
{
this.key3 = key3;
}
38. Для доступа к полям ввода и кнопкам формы добавьте следующие set-методы:
public void setTextBox1Text(string text)
{
this.textBox1.Text = text;
}
public void setTextBox2Text(string text)
{
this.textBox2.Text = text;
}
public void setTextBox3Text(string text)
{
this.textBox3.Text = text;
}
public void setTextBox4Text(string text)
{
this.textBox4.Text = text;
}
public void setButton1Visible(bool visible)
{
this.button1.Visible = visible;
}
public void setButton2Visible(bool visible)
{
this.button2.Visible = visible;
}
39. Создайте обработчики нажатия на кнопки «Добавить» и «Заменить»:
//Обработчик нажатия на "Добавить"
private void button1_Click(object sender, EventArgs e)
{
DAOFactory dao = new NHibernateDAOFactory(session);
IGroupDAO groupDAO = dao.getGroupDAO();
Group group = groupDAO.getGroupByName(key1);
Student student = new Student();
student.FirstName = textBox1.Text;
student.LastName = textBox2.Text;
student.Sex = textBox3.Text[0];
student.Year = Int32.Parse(textBox4.Text);
group.StudentList.Add(student);
student.Group = group;
groupDAO.SaveOrUpdate(group);
perent.fillDataGridView2(key1);
this.Visible = false;
}
//Обработчик нажатия на "Заменить"
private void button2_Click(object sender, EventArgs e)
{
DAOFactory dao = new NHibernateDAOFactory(session);
IStudentDAO studentDAO = dao.getStudentDAO();
Student student = studentDAO
.getStudentByGroupFirstNameAndLastName(key1, key2, key3);
student.FirstName = textBox1.Text;
student.LastName = textBox2.Text;
student.Sex = textBox3.Text[0];
student.Year = Int32.Parse(textBox4.Text);
studentDAO.SaveOrUpdate(student);
this.Visible = false;
perent.fillDataGridView2(key1);
}
40. Откройте Form1 с помощью редактора CSharp. Для удобства работы с Form4 добавьте метод:
private Form4 getForm4()
{
if (form4 == null)
{
form4 = new Form4();
}
form4.setSession(session);
form4.setPerent(this);
return form4;
}
41. Заполните обработчики нажатия на «Добавить», «Удалить», «Заменить» контекстного меню студента:
//Нажатие на "Добавить" в контекстном меню студента
private void добавитьToolStripMenuItem1_Click(object sender, EventArgs e)
{
int selectedRow = dataGridView1.SelectedCells[0].RowIndex;
string key = (string)dataGridView1.Rows[selectedRow].Cells[0].Value;
getForm4().Visible = true;
getForm4().setButton1Visible(true);
getForm4().setButton2Visible(false);
getForm4().setTextBox1Text("");
getForm4().setTextBox2Text("");
getForm4().setTextBox3Text("");
getForm4().setTextBox4Text("");
getForm4().setKey1(key);
}
//Нажатие на "Удалить" в контекстном меню студента
private void удалитьToolStripMenuItem1_Click(object sender, EventArgs e)
{
int selectedRow = dataGridView1.SelectedCells[0].RowIndex;
string key1 = (string)dataGridView1.Rows[selectedRow].Cells[0].Value;
selectedRow = dataGridView2.SelectedCells[0].RowIndex;
string key2 = (string)dataGridView2.Rows[selectedRow].Cells[0].Value;
selectedRow = dataGridView2.SelectedCells[0].RowIndex;
string key3 = (string)dataGridView2.Rows[selectedRow].Cells[1].Value;
DAOFactory dao = new NHibernateDAOFactory(session);
IStudentDAO studentDAO = dao.getStudentDAO();
Student student = studentDAO
.getStudentByGroupFirstNameAndLastName(key1, key2, key3);
student.Group.StudentList.Remove(student);
studentDAO.Delete(student);
fillDataGridView2(key1);
}
//Нажатие на "Заменить" в контекстном меню студента
private void изменитьToolStripMenuItem1_Click(object sender, EventArgs e)
{
int selectedRow = dataGridView1.SelectedCells[0].RowIndex;
string key1 = (string)dataGridView1.Rows[selectedRow].Cells[0].Value;
selectedRow = dataGridView2.SelectedCells[0].RowIndex;
string key2 = (string)dataGridView2.Rows[selectedRow].Cells[0].Value;
selectedRow = dataGridView2.SelectedCells[0].RowIndex;
string key3 = (string)dataGridView2.Rows[selectedRow].Cells[1].Value;
DAOFactory dao = new NHibernateDAOFactory(session);
IStudentDAO studentDAO = dao.getStudentDAO();
Student student = studentDAO
.getStudentByGroupFirstNameAndLastName(key1, key2, key3);
getForm4().Visible = true;
getForm4().setTextBox1Text(student.FirstName);
getForm4().setTextBox2Text(student.LastName);
getForm4().setTextBox3Text(student.Sex.ToString());
getForm4().setTextBox4Text(student.Year.ToString());
getForm4().setKey1(key1);
getForm4().setKey2(key2);
getForm4().setKey3(key3);
getForm4().setButton1Visible(false);
getForm4().setButton2Visible(true);
}
42. Добавьте обработчик на изменение размеров формы:
private void Form1_Resize(object sender, EventArgs e)
{
this.dataGridView1.Columns["Column1"].Width =
(this.dataGridView1.Width / 3) - 1;
this.dataGridView1.Columns["Column2"].Width =
(this.dataGridView1.Width / 3) - 1;
this.dataGridView1.Columns["Column3"].Width =
(this.dataGridView1.Width / 3) - 1;
this.dataGridView2.Columns["Column4"].Width =
System.Convert.ToInt32(this.dataGridView2.Width * 0.3) - 1;
this.dataGridView2.Columns["Column5"].Width =
System.Convert.ToInt32(this.dataGridView2.Width * 0.3) - 1;
this.dataGridView2.Columns["Column6"].Width =
System.Convert.ToInt32(this.dataGridView2.Width * 0.1) - 1;
this.dataGridView2.Columns["Column7"].Width =
System.Convert.ToInt32(this.dataGridView2.Width * 0.3) - 1;
}
Результат работы приложения представлен на рисунке 4.4.
Рисунок 4.4 – Результат работы приложения
Задание на лабораторную работу
Написать приложение, описанное в ходе выполнения лабораторной работы, которое может работать с двумя таблицами СУБД. В отличие от приложения, описанного в лабораторной работе, предметную область необходимо выбрать с таблицы 4.1. Номер варианта определяется по последней цифре зачетной книжки.
Таблица 4.1 – Варианты заданий
Номер варианта | Предметная область |
Пиццерия (Официант, Посетитель) | |
Магазин (Поставщик, Товар) | |
Супермаркет (Продавец, Товар) | |
Отделение милиции (Милиционер, Нарушитель) | |
Больница (Врач, Пациент) | |
Кинотеатр (Кинозал, Посетитель) | |
Корабль (Каюта, Пассажир) | |
Предприятие (Отдел, Сотрудник) | |
Библиотека (Книга, Читатель) |
Содержание отчета
- фамилия и имя исполнителя лабораторной работы;
- номер и название лабораторной работы;
- цель лабораторной работы;
- краткие теоретические сведенья на одну страницу;
- ход работы (листинги программ, скриншоты программ);
- выводы о проделанной работе.
Контрольные вопросы
1. Что такое ORM?
2. Чем отличается NHibernate от Fluent NHibernate?
3. Как в Fluent NHibernate спроецировать поле класса на базу данных.
4. Как задать связи между объектами в NHibernate?
5. Как задать связи между объектами в Fluent NHibernate?
6. Связь HasOne. Назначение и синтаксис.
7. Связь HasMany. Назначение и синтаксис.
8. Связь HasManyToMany. Назначение и синтаксис.
5 Лабораторная работа № 5
ASP.NET
Цель работы
Изучить возможности технологии ASP.NET, получить практические навыки по работе с ASP.NET.
Теоретические сведенья