Способы выборки объектов в 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.

Способы выборки объектов в Fluent NHibernate - student2.ru

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 к проекту (нажмите правой кнопкой на «Ссылки» в дереве объектов потом на «Добавить ссылку…», перейдите на закладку «Обзор», выберите необходимые файлы).

Способы выборки объектов в Fluent NHibernate - student2.ru

Теперь все готово для создания слоя доступа к данным 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.

Способы выборки объектов в Fluent NHibernate - student2.ru

Рисунок 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.

Способы выборки объектов в Fluent NHibernate - student2.ru

Рисунок 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

Способы выборки объектов в Fluent NHibernate - student2.ru

Рисунок 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.

Способы выборки объектов в Fluent NHibernate - student2.ru

Рисунок 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.

Теоретические сведенья

Наши рекомендации