Эх, приключилось тут...
Как то раз, топая домой под шафе услышал из под машины странные звуки. Думал человек застрял... Гляжу, вылазит собако, щенок. Погладил... Жалко. Пошел себе дальше потихоньку. Смотрю щенок то за мной плетется! Ужас! Что делать??? Ну дошли мы с ним до моего дома. КУпил ему по дороге сосиску. Сожрал с радостью!) Тут нам через дорогу переходить! Взял на руки сорванца, так он и уснул у меня на руках сразу...
Пришли домой. ПОнимаю что животное у меня жить не может... Аллергия сильная у мну на собак, кошек и всю остальную живность... Эх. ПОмыл я гада, расчихался весь я. И мы легли спать. Стоит заметить что щенок, которого я назвал Сява, бодрячком пацанчик:-), уснул сразу!
Следующий день мы провели отлично! Кусались, ели, гадили и спали! Но аллергия не давала мне покоя. Покрылся весь пятнами я уже, чихал... Задыхаться начал. Пришлось расставаться.:-(((( Ужас! Отнес я его в подвал... Через пол часа пошел опять за ним, не смог вынести разлуки! Его уже не было. Все облазил, нет Сявки... Мда.
Сявко:

Как то раз, топая домой под шафе услышал из под машины странные звуки. Думал человек застрял... Гляжу, вылазит собако, щенок. Погладил... Жалко. Пошел себе дальше потихоньку. Смотрю щенок то за мной плетется! Ужас! Что делать??? Ну дошли мы с ним до моего дома. КУпил ему по дороге сосиску. Сожрал с радостью!) Тут нам через дорогу переходить! Взял на руки сорванца, так он и уснул у меня на руках сразу...
Пришли домой. ПОнимаю что животное у меня жить не может... Аллергия сильная у мну на собак, кошек и всю остальную живность... Эх. ПОмыл я гада, расчихался весь я. И мы легли спать. Стоит заметить что щенок, которого я назвал Сява, бодрячком пацанчик:-), уснул сразу!
Следующий день мы провели отлично! Кусались, ели, гадили и спали! Но аллергия не давала мне покоя. Покрылся весь пятнами я уже, чихал... Задыхаться начал. Пришлось расставаться.:-(((( Ужас! Отнес я его в подвал... Через пол часа пошел опять за ним, не смог вынести разлуки! Его уже не было. Все облазил, нет Сявки... Мда.
Сявко:
Всем привет. Что такое GenericDao, вы должны знать, но если не знаете:
DAO( сокр. от англ. Data Access Objects) - объекты для доступа к данным
Generic означает что мы будем использовать шаблоны классов (generic), доступные в C#, для создания такого интерфейса, который позволит работать со всеми нашими классами NHibernate.
1. Создание интерфейса GenericDao
Итак приступим. В прошлой статье я говорил как настроить NHibernate. Какой должен быть файл настроек приложения и т.д.
Для начала рассмотрим то, как же происходит работа с NHibernate (далее хибер, хибернейт), для доступа к БД.
Разберем класс, который нам позволяет настроить NHibernate для работы с нашими объектами, этот класс мы просто рассмотрим, нигде использовать его не будем:
**************************************** **************************************** ********
public class DataController
{
private ISessionFactory _sessions;
public DataController()
{
Configuration cfg = new Configuration();
cfg.AddClass(typeof (DataElement));//Указание классов хибера
cfg.AddClass(typeof(Pins));
cfg.AddClass(typeof (Properties));
cfg.AddClass(typeof(Library));
_sessions = cfg.BuildSessionFactory();//Создание фабрики сессий
}
}
**************************************** **************************************** ********
В конструкторе мы видим что создается объект класса Configuration, который нам следует сконфигурировать определенным образом. Мы указываем какие хибер классы мы имеем. После этого строим фабрику сессий. После чего фабрика сессий позволяет нам открывать сессию для работы именно с теми классами которые мы указали. Далее рассмотрим как же нам, скажем, сохранить данные в БД...
**************************************** ************
public DataElement SaveElement(DataElement el)
{
ISession session = _sessions.OpenSession();//Октрываем сессию
try
{
session.Save(el); //Сохраняем элемент
return el; //Возвращаем его, для получения его PK, если PK у нас генерируется
}
catch (HibernateException e)
{
throw e;
}
finally
{
session.Close();//закрываем сессию
}
}
**************************************** ************
Вот так вот просто мы можем работать с объектами класса DataElement. Я думаю тут все понятно что происходит. Но получается, что такие методы нам нужно писать для всех классов... Желания у всех нет писать это, тем более если классов очень много. Не забываем про методы Insert, Update, Delete. Итого у нас четыре хибер класса, для каждого минимум по четыре метода, итого 16 методов. Лень...
Вот тут приходит на помощь DAO + generic.
Итак давайте попробуем создать интерфейс общий для всех хибер объектов, словом *type* мы пометим те типы которые являются хибер классами, т.е. это может быть любой из используемых у нас хибер классов. В моей БД, у всех таблиц PK - это int поле.
***********************************
public interface IGenericDao
{
*type* Get(int id);
*type* Save(*type*obj);
*type* SaveOrUpdate(*type* obj);
void Delete(*type* obj);
}
***********************************
Мы видим что для всех классов требуется четыре метода (имеется ввиду минимум)... Удивительно... Но как же нам передавать грамотно тип? А вот так:
*************************************
public interface IGenericDao<T, ID>
{
T Get(ID id);
T Save(T obj);
T SaveOrUpdate(T obj);
void Delete(T obj);
}
*************************************
Здесь мы начинаем использовать шаблон класса. Даже два. Первый (T) это шаблон для хибер класса, второй(ID) это шаблон для типа которым является PK. Т.е. мы сможем брать поля из БД, не только по PK с типом int, но и скажем string.
Вот мы создали интерфейс GenericDao, теперь надо создать класс который будет реализовывать этот интерфейс. Но для начала вспомним о сессиях.
2. Создание фабрики сессий
Мы помним что для того что бы взять, сохранить, обновить или удалить данные из БД, нам надо открыть сессию. И еще замечу, что если мы взяли данные, передали их в объект хибер класса, и закрыли сессию, то если у нас отключено Lazy (по умолчанию отключено), данные в объекте будут не доступны. Из за чего это? Из за того что прокси класс ссылается через сессию на требуемые нам данные (что такое прокси класс, читай документацию к хиберу). После закрытия сессии, получается что прокси класс ссылается на недоступную нам ссылку. Т.е. Получается что сессию мы должны хранить. Как же это сделать? Сессия описывается через интерфейс ISession. И берем мы сессию из фабрики сессий. Как же нам красиво это сделать? А вот как:
**************************************** ************
public class SessionFactory
{
public static void Init() //Инициализация фабрики сессий
{
Configuration cfg = new Configuration();
cfg.AddAssembly("Win.Objects"); //Конфигурируем NHibernate. Здесь мы указываем на сборку, в которой хранятся мои хибер классы.
sessionFactory = cfg.BuildSessionFactory();
}
private static ISessionFactory sessionFactory; //Объект фабрики сессий, реализованный в хибере
private static ISession threadSession //Сама сессия
{
get
{
return (ISession)CallContext.GetData("THREAD_SE SSION"); //Сессию мы храним в контексте, вот так работать с контекстом
}
set
{
CallContext.SetData("THREAD_SESSION", value);
}
}
public static ISession GetSession() //Метод возвращающий нам сессию.
{
ISession session = threadSession; //Берем сессию из контекста
if (session == null) //Смотрим "метрва" ли она
{
session = sessionFactory.OpenSession(); //Через фабрику сессий открываем сессию
threadSession = session; //Записываем ее в контекс
}
return session; //Возвращаем
}
}
**************************************** ***********
Вот так все просто. Получается что сессия хранится в контексте, когда она нам нужна, мы вызываем метод GetSession(), там проверяется "Жива" ли сессия или нет, если нет - создаем новую, если да - возвращаем "живую". Что касается инициализации, то ее надо вызвать один раз в любом месте своей программы, но до того как начали использовать сессию. Скажем в конструкторе главной формы. Вот и все. Разобрались... Теперь посмотрим на реализацию интерфейса IGenericDao.
3. Реализация IGenericDao
У нас есть интерфейс, через который мы реализуем DAO, у нас есть класс для работы с сессией, теперь нам осталось написать методы CRUD(Create, Read, Update, Delete) для работы через generic. Так это происходит:
**************************************
public class GenericImpl<T, ID> : IGenericDao<T, ID> //Реализуем интерфейс IGenericDao
{
private ISession session //Здесь метод на взятие сессии
{
get
{
return SessionFactory.GetSession(); //Используем нашу фабрику сессий.
}
}
private Type _type = typeof (T); //Тип хибер класса, с которым работаем.
public T Get(ID id) //Метод взятия данных
{
try
{
T result = (T) session.Load(_type, id); //Говорим что возвращаем тип T и загружаем его используя сессию через метод Load
return result; //Возвращаем
}
catch (HibernateException e)
{
throw e;
}
}
public T Save(T obj)
{
try
{
session.Save(obj);
return obj;
}
catch (HibernateException e)
{
throw e;
}
}
public T SaveOrUpdate(T obj)
{
session.SaveOrUpdate(obj);
return obj;
}
public void Delete(T obj)
{
session.Delete(obj);
}
}
**************************************
И опять все до смешного просто... Теперь мы можем создавать GenericDao для любого нашего хибер класса. Теперь мы можем использовать класс GenericImpl для работы с любым нашим объектом. Как это сделать? Вот так:
*******************************
GenericImpl<Library, int> libdao = new GenericImpl<Library, int>(); //Вот инструмент для работы с объектами хибер класса Library
Library lib = new Library(); //Создаем объект хибер класса
lib.Name = "Новая библиотека"; //Заполняем
libdao.Save(lib);//Так сохраняем
libdao.Get(1);//берем
libdao.Delete(lib);//Удаляем
libdao.SaveOrUpdate(lib);//Обновляем
*******************************
Ну красиво, неправда ли? Но на этом мы не остановимся. Мне кажется что вам может не понравится то как создается DAO. Попробуем облегчить себе жизнь. Как? Создадим фабрику DAO для каждого хибер класса.
4. Фабрика DAO
Что мы будем делать? Мы создадим для каждого класса свое DAO, уникальное, но при этом мы не напишем больше ни одного метода CRUD. Как так сделать? Просто. Но по порядку...
Мы создадим интерфейс DAO для каждого хибер класса, просто наследуя его от базового IGenericDao, но с указанием того с каким хибер классом мы будем работать:
*************************************
public interface IDataElementDao : IGenericDao<DataElement,int>{}
public interface ILibraryDao : IGenericDao<Library, int> { }
public interface IPinsDao : IGenericDao<Pins, int> { }
public interface IPropertiesDao : IGenericDao<Properties, int> { }
*************************************
Минус конечно что для каждого класса надо объявлять свой интерфейс, но зато не надо писать CRUD методы. Дальше мы сделаем интерфейс для фабрики DAO, которая будет нам поставлять уже готовые интерфейсы Dao для каждого хибер класса:
*************************************
public interface IDaoFactory
{
IDataElementDao GetDataElementDao();
ILibraryDao GetLibraryDao();
IPinsDao GetPinsDao();
IPropertiesDao GetPropertiesDao();
}
*************************************
Я думаю все понятно что это. И что бы было все совсем красиво, создадим классы, которые будут реализовывать IGenericDAO для каждого отдельного хибер класса:
**************************************
public class HDataElement : GenericImpl<DataElement,int>, IDataElementDao{}
public class HLibrary : GenericImpl<Library,int>, ILibraryDao{}
public class HPins : GenericImpl<Pins,int>, IPinsDao{}
public class HProperties : GenericImpl<Properties, int>, IPropertiesDao{}
**************************************
Получается что мы должны реализовать интерфейс DAO для каждого хибер класса, и мы реализуем его наследовав базовый GenericImpl с указанием хибер класса. И реализуем фабрику DAO:
**************************************
ublic class FactoryDao : IDaoFactory
{
public IDataElementDao GetDataElementDao()
{
return new HDataElement();
}
public ILibraryDao GetLibraryDao()
{
return new HLibrary();
}
public IPinsDao GetPinsDao()
{
return new HPins();
}
public IPropertiesDao GetPropertiesDao()
{
return new HProperties();
}
}
**************************************
Вот так мы получаем готовые объекты DAO для работы с любым хибер классом. Как этим пользоваться? Вот так:
**************************************
IDaoFactory fact = new FactoryDao(); //Создаем фабрику дао
ILibraryDao libdao = fact.GetLibraryDao();//берем дао для Library
Library lib = new Library();
lib.Name = "Новая библиотека";
libdao.Save(lib);
libdao.Get(1);
libdao.Delete(lib);
libdao.SaveOrUpdate(lib);
IDataElementDao eldao = fact.GetDataElementDao();//Берем ДАО для DataElement и можем дальше работать с ним.
**************************************
ЗАКЛЮЧЕНИЕ
Хочется добавить что если есть не решенные вопросы, то озвучивайте их и тогда может быть ваш вопрос попадет в тему следующих статей.
Для тех кому и этого мало, то идем СЮДА. Здесь описано как еще больше облегчить наши проблемы с использованием Spring FrameWork и его SpringAOP. Вещь крайне полезная, но очень прихотливая.
Ну вот и все. Надеюсь всем все понятно. Претензии как всегда все принимаются и будут услышаны. Надеюсь пригодится.)
DAO( сокр. от англ. Data Access Objects) - объекты для доступа к данным
Generic означает что мы будем использовать шаблоны классов (generic), доступные в C#, для создания такого интерфейса, который позволит работать со всеми нашими классами NHibernate.
1. Создание интерфейса GenericDao
Итак приступим. В прошлой статье я говорил как настроить NHibernate. Какой должен быть файл настроек приложения и т.д.
Для начала рассмотрим то, как же происходит работа с NHibernate (далее хибер, хибернейт), для доступа к БД.
Разберем класс, который нам позволяет настроить NHibernate для работы с нашими объектами, этот класс мы просто рассмотрим, нигде использовать его не будем:
****************************************
public class DataController
{
private ISessionFactory _sessions;
public DataController()
{
Configuration cfg = new Configuration();
cfg.AddClass(typeof (DataElement));//Указание классов хибера
cfg.AddClass(typeof(Pins));
cfg.AddClass(typeof (Properties));
cfg.AddClass(typeof(Library));
_sessions = cfg.BuildSessionFactory();//Создание фабрики сессий
}
}
****************************************
В конструкторе мы видим что создается объект класса Configuration, который нам следует сконфигурировать определенным образом. Мы указываем какие хибер классы мы имеем. После этого строим фабрику сессий. После чего фабрика сессий позволяет нам открывать сессию для работы именно с теми классами которые мы указали. Далее рассмотрим как же нам, скажем, сохранить данные в БД...
****************************************
public DataElement SaveElement(DataElement el)
{
ISession session = _sessions.OpenSession();//Октрываем сессию
try
{
session.Save(el); //Сохраняем элемент
return el; //Возвращаем его, для получения его PK, если PK у нас генерируется
}
catch (HibernateException e)
{
throw e;
}
finally
{
session.Close();//закрываем сессию
}
}
****************************************
Вот так вот просто мы можем работать с объектами класса DataElement. Я думаю тут все понятно что происходит. Но получается, что такие методы нам нужно писать для всех классов... Желания у всех нет писать это, тем более если классов очень много. Не забываем про методы Insert, Update, Delete. Итого у нас четыре хибер класса, для каждого минимум по четыре метода, итого 16 методов. Лень...
Вот тут приходит на помощь DAO + generic.
Итак давайте попробуем создать интерфейс общий для всех хибер объектов, словом *type* мы пометим те типы которые являются хибер классами, т.е. это может быть любой из используемых у нас хибер классов. В моей БД, у всех таблиц PK - это int поле.
***********************************
public interface IGenericDao
{
*type* Get(int id);
*type* Save(*type*obj);
*type* SaveOrUpdate(*type* obj);
void Delete(*type* obj);
}
***********************************
Мы видим что для всех классов требуется четыре метода (имеется ввиду минимум)... Удивительно... Но как же нам передавать грамотно тип? А вот так:
*************************************
public interface IGenericDao<T, ID>
{
T Get(ID id);
T Save(T obj);
T SaveOrUpdate(T obj);
void Delete(T obj);
}
*************************************
Здесь мы начинаем использовать шаблон класса. Даже два. Первый (T) это шаблон для хибер класса, второй(ID) это шаблон для типа которым является PK. Т.е. мы сможем брать поля из БД, не только по PK с типом int, но и скажем string.
Вот мы создали интерфейс GenericDao, теперь надо создать класс который будет реализовывать этот интерфейс. Но для начала вспомним о сессиях.
2. Создание фабрики сессий
Мы помним что для того что бы взять, сохранить, обновить или удалить данные из БД, нам надо открыть сессию. И еще замечу, что если мы взяли данные, передали их в объект хибер класса, и закрыли сессию, то если у нас отключено Lazy (по умолчанию отключено), данные в объекте будут не доступны. Из за чего это? Из за того что прокси класс ссылается через сессию на требуемые нам данные (что такое прокси класс, читай документацию к хиберу). После закрытия сессии, получается что прокси класс ссылается на недоступную нам ссылку. Т.е. Получается что сессию мы должны хранить. Как же это сделать? Сессия описывается через интерфейс ISession. И берем мы сессию из фабрики сессий. Как же нам красиво это сделать? А вот как:
****************************************
public class SessionFactory
{
public static void Init() //Инициализация фабрики сессий
{
Configuration cfg = new Configuration();
cfg.AddAssembly("Win.Objects"); //Конфигурируем NHibernate. Здесь мы указываем на сборку, в которой хранятся мои хибер классы.
sessionFactory = cfg.BuildSessionFactory();
}
private static ISessionFactory sessionFactory; //Объект фабрики сессий, реализованный в хибере
private static ISession threadSession //Сама сессия
{
get
{
return (ISession)CallContext.GetData("THREAD_SE
}
set
{
CallContext.SetData("THREAD_SESSION", value);
}
}
public static ISession GetSession() //Метод возвращающий нам сессию.
{
ISession session = threadSession; //Берем сессию из контекста
if (session == null) //Смотрим "метрва" ли она
{
session = sessionFactory.OpenSession(); //Через фабрику сессий открываем сессию
threadSession = session; //Записываем ее в контекс
}
return session; //Возвращаем
}
}
****************************************
Вот так все просто. Получается что сессия хранится в контексте, когда она нам нужна, мы вызываем метод GetSession(), там проверяется "Жива" ли сессия или нет, если нет - создаем новую, если да - возвращаем "живую". Что касается инициализации, то ее надо вызвать один раз в любом месте своей программы, но до того как начали использовать сессию. Скажем в конструкторе главной формы. Вот и все. Разобрались... Теперь посмотрим на реализацию интерфейса IGenericDao.
3. Реализация IGenericDao
У нас есть интерфейс, через который мы реализуем DAO, у нас есть класс для работы с сессией, теперь нам осталось написать методы CRUD(Create, Read, Update, Delete) для работы через generic. Так это происходит:
**************************************
public class GenericImpl<T, ID> : IGenericDao<T, ID> //Реализуем интерфейс IGenericDao
{
private ISession session //Здесь метод на взятие сессии
{
get
{
return SessionFactory.GetSession(); //Используем нашу фабрику сессий.
}
}
private Type _type = typeof (T); //Тип хибер класса, с которым работаем.
public T Get(ID id) //Метод взятия данных
{
try
{
T result = (T) session.Load(_type, id); //Говорим что возвращаем тип T и загружаем его используя сессию через метод Load
return result; //Возвращаем
}
catch (HibernateException e)
{
throw e;
}
}
public T Save(T obj)
{
try
{
session.Save(obj);
return obj;
}
catch (HibernateException e)
{
throw e;
}
}
public T SaveOrUpdate(T obj)
{
session.SaveOrUpdate(obj);
return obj;
}
public void Delete(T obj)
{
session.Delete(obj);
}
}
**************************************
И опять все до смешного просто... Теперь мы можем создавать GenericDao для любого нашего хибер класса. Теперь мы можем использовать класс GenericImpl для работы с любым нашим объектом. Как это сделать? Вот так:
*******************************
GenericImpl<Library, int> libdao = new GenericImpl<Library, int>(); //Вот инструмент для работы с объектами хибер класса Library
Library lib = new Library(); //Создаем объект хибер класса
lib.Name = "Новая библиотека"; //Заполняем
libdao.Save(lib);//Так сохраняем
libdao.Get(1);//берем
libdao.Delete(lib);//Удаляем
libdao.SaveOrUpdate(lib);//Обновляем
*******************************
Ну красиво, неправда ли? Но на этом мы не остановимся. Мне кажется что вам может не понравится то как создается DAO. Попробуем облегчить себе жизнь. Как? Создадим фабрику DAO для каждого хибер класса.
4. Фабрика DAO
Что мы будем делать? Мы создадим для каждого класса свое DAO, уникальное, но при этом мы не напишем больше ни одного метода CRUD. Как так сделать? Просто. Но по порядку...
Мы создадим интерфейс DAO для каждого хибер класса, просто наследуя его от базового IGenericDao, но с указанием того с каким хибер классом мы будем работать:
*************************************
public interface IDataElementDao : IGenericDao<DataElement,int>{}
public interface ILibraryDao : IGenericDao<Library, int> { }
public interface IPinsDao : IGenericDao<Pins, int> { }
public interface IPropertiesDao : IGenericDao<Properties, int> { }
*************************************
Минус конечно что для каждого класса надо объявлять свой интерфейс, но зато не надо писать CRUD методы. Дальше мы сделаем интерфейс для фабрики DAO, которая будет нам поставлять уже готовые интерфейсы Dao для каждого хибер класса:
*************************************
public interface IDaoFactory
{
IDataElementDao GetDataElementDao();
ILibraryDao GetLibraryDao();
IPinsDao GetPinsDao();
IPropertiesDao GetPropertiesDao();
}
*************************************
Я думаю все понятно что это. И что бы было все совсем красиво, создадим классы, которые будут реализовывать IGenericDAO для каждого отдельного хибер класса:
**************************************
public class HDataElement : GenericImpl<DataElement,int>, IDataElementDao{}
public class HLibrary : GenericImpl<Library,int>, ILibraryDao{}
public class HPins : GenericImpl<Pins,int>, IPinsDao{}
public class HProperties : GenericImpl<Properties, int>, IPropertiesDao{}
**************************************
Получается что мы должны реализовать интерфейс DAO для каждого хибер класса, и мы реализуем его наследовав базовый GenericImpl с указанием хибер класса. И реализуем фабрику DAO:
**************************************
ublic class FactoryDao : IDaoFactory
{
public IDataElementDao GetDataElementDao()
{
return new HDataElement();
}
public ILibraryDao GetLibraryDao()
{
return new HLibrary();
}
public IPinsDao GetPinsDao()
{
return new HPins();
}
public IPropertiesDao GetPropertiesDao()
{
return new HProperties();
}
}
**************************************
Вот так мы получаем готовые объекты DAO для работы с любым хибер классом. Как этим пользоваться? Вот так:
**************************************
IDaoFactory fact = new FactoryDao(); //Создаем фабрику дао
ILibraryDao libdao = fact.GetLibraryDao();//берем дао для Library
Library lib = new Library();
lib.Name = "Новая библиотека";
libdao.Save(lib);
libdao.Get(1);
libdao.Delete(lib);
libdao.SaveOrUpdate(lib);
IDataElementDao eldao = fact.GetDataElementDao();//Берем ДАО для DataElement и можем дальше работать с ним.
**************************************
ЗАКЛЮЧЕНИЕ
Хочется добавить что если есть не решенные вопросы, то озвучивайте их и тогда может быть ваш вопрос попадет в тему следующих статей.
Для тех кому и этого мало, то идем СЮДА. Здесь описано как еще больше облегчить наши проблемы с использованием Spring FrameWork и его SpringAOP. Вещь крайне полезная, но очень прихотливая.
Ну вот и все. Надеюсь всем все понятно. Претензии как всегда все принимаются и будут услышаны. Надеюсь пригодится.)
Итак приступим. Что у нас есть? У нас БД. Допустим на MSSql сервере, скажем 2005, но это не важно. БД любая. Пишем на C# под 2005 VS. Итак что же нам надо что бы все хорошо сделать?
1. Программка MyGeneration(далее майген или МГ). Я использую версию 1.3
2. Шаблон NHibernate Object Mapping автора k-dub.
Все эти вещи берем тут.
Ставим МГ. Запускаем. Настраиваем подключение к нашей БД. Выбираем шаблон и запускаем.
Появится окно:

Выбираем NameSpace для классов. Префикс для скрытых членов класса. Требуемые таблицы. И остальные настройки по своему усмотрению. Жмем ок. У нас сгенерится hbm.xml файлы и классы для хибера.
Далее создаем проект в студии. Для удобства создаем новую папку в сборке. Скажем Objects. И добавляем туда все сгенерированные файлы. ИМЕННО ВСЕ!
Далее нам надо указать у всех hbm.xml файлов что они являются Embedded Resource. Это делается в свойствах файла.
Ну вот объекты готовы. Отлично. Хлопаем в ладоши, хаваем булочки. Но нам надо настроить хибер на работу с БД и связать его с объектами.
Добавляем хиберовские сборки. Где их взять? Тут.
Нужны следующие сборки:
NHibernate.dll
Также нам нужно создать файл настроек приложения. Туда следующее:
**************************************** *****
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="nhibernate" type="System.Configuration.NameValueSect ionHandler, System, Version=1.0.5000.0,Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</configSections>
<nhibernate>
<add key="hibernate.show_sql" value="true" />
<add key="hibernate.connection.provider" value="NHibernate.Connection.DriverConne ctionProvider" />
<add key="hibernate.dialect" value="NHibernate.Dialect.MsSql2000Diale ct" />
<add key="hibernate.connection.driver_class" value="NHibernate.Driver.SqlClientDriver" />
<add key="hibernate.connection.connection_str ing" value="Data Source=kn002\sqlexpress;Initial Catalog=Diplom;Integrated Security=True" />
</nhibernate>
</configuration>
*********************************
Смотрим все ли совпадает. У мну хибер 1.2.0
В теге
<add key="hibernate.connection.connection_str ing" value="Data Source=kn002\sqlexpress;Initial Catalog=Diplom;Integrated Security=True" /> указываем путь к своей БД. Диалект можно поставить 2005.
Теперь можно создать класс контроллер, который будет позволять нам работать с объектами хибера.
Пример:
**************************************** ***********
using NHibernate;
using NHibernate.Cfg;
using WindowsApplication2.Objects;
namespace WindowsApplication2
{
public class DataController
{
private ISessionFactory _sessions;
public DataController()
{
Configuration cfg = new Configuration();
cfg.AddClass(typeof (DataElement));
cfg.AddClass(typeof(Pins));
cfg.AddClass(typeof (WindowsApplication2.Objects.Properties) );
cfg.AddClass(typeof(Library));
_sessions = cfg.BuildSessionFactory();
//new SchemaExport(cfg).Create(true, true);//Для создания бд раскоментить
}
public int SaveElement(DataElement el)
{
ISession session = _sessions.OpenSession();
ITransaction tx = null;
try
{
tx = session.BeginTransaction();
int ID = (int)session.Save(el);
tx.Commit();
return ID;
}
catch (HibernateException e)
{
if (tx != null) tx.Rollback();
throw e;
}
finally
{
session.Close();
}
}
}
}
**************************************** ***
Извините за названия сборок.)
Что тут происходит? В конструкторе контроллера мы начинаем конфигурировать хибернейт. И строим сессию исходя из конфига.
Закоменченная строка позволяет создавать БД, исходя из конфига. Мы добавляем наши классы хибера cfg.AddClass(typeof (DataElement)); и так для каждого класса хибера.
Также тут представлен метод сохранения объекта. Работаем с хибером следующем образом:
Открываем сессию. Начинаем транзакцию. Делаем что нам нужно. Подтверждаем транзакцию. Если ошибки, отколоняем транзакцию. И всегда закрываем сессию. Для работы метода передаем хиберовский объект.
Разберемся получше с объектами хибернейта.
Маппинг:
**********************
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="Diplom.Data.Pins,Diplom.Data" table="Pins" lazy="false" >
<id name="Id" column="ID" type="Int32" unsaved-value="0">
<generator class="native"/>
</id>
<property column="X" type="Int32" name="X" />
<property column="Y" type="Int32" name="Y" />
<many-to-one name="FkElement" column="FKElement" class="Diplom.Data.DataElement,Diplom.Da ta" />
<property column="Number" type="Int32" name="Number" />
</class>
</hibernate-mapping>
**********************
<id name="Id" column="ID" type="Int32" unsaved-value="0">
<generator class="native"/>
</id>
это описание PK. Name - имя в классе хибера. Column - имя в БД. И выбираем тип генератора. О всех генераторах смотри в доках по хиберу.
<property column="Y" type="Int32" name="Y" /> описание столбца. Тоже самое все.
<many-to-one name="FkElement" column="FKElement" class="Diplom.Data.DataElement,Diplom.Da ta" /> описание FK. Имя в классе. Имя в БД. И класс на который ключ ссылается.
В классе объекта хибера, все паблик методы должны быть виртуальными! В маппинге обрати внимание на <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"> Должно быть именно 2.2. в нашей версии хибера.
В маппинге объектов <class name="WindowsApplication2.Objects.DataEl ement,WindowsApplication2" table="DataElement"> имя класса дается следующим образом: Полностью Namespace класса + имя класса, после запятой имя сборки. Так для всех указаний на классы.
Так же отмечу что шаблон немного надо подправить будет, который используется в МГ при генерировании объектов. Надеюсь проблем у вас при это не возникнет. Но если надо, могу выложить.
Ну вот в принципе небольшой пример по поводу того как начать быстро работать с хибером. Я рассказывал именно о том как начать быстро работать, а не о том как устроен хибер. Будут вопросы, всегда отвечу.)
1. Программка MyGeneration(далее майген или МГ). Я использую версию 1.3
2. Шаблон NHibernate Object Mapping автора k-dub.
Все эти вещи берем тут.
Ставим МГ. Запускаем. Настраиваем подключение к нашей БД. Выбираем шаблон и запускаем.
Появится окно:
Выбираем NameSpace для классов. Префикс для скрытых членов класса. Требуемые таблицы. И остальные настройки по своему усмотрению. Жмем ок. У нас сгенерится hbm.xml файлы и классы для хибера.
Далее создаем проект в студии. Для удобства создаем новую папку в сборке. Скажем Objects. И добавляем туда все сгенерированные файлы. ИМЕННО ВСЕ!
Далее нам надо указать у всех hbm.xml файлов что они являются Embedded Resource. Это делается в свойствах файла.
Ну вот объекты готовы. Отлично. Хлопаем в ладоши, хаваем булочки. Но нам надо настроить хибер на работу с БД и связать его с объектами.
Добавляем хиберовские сборки. Где их взять? Тут.
Нужны следующие сборки:
NHibernate.dll
Также нам нужно создать файл настроек приложения. Туда следующее:
****************************************
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="nhibernate" type="System.Configuration.NameValueSect
</configSections>
<nhibernate>
<add key="hibernate.show_sql" value="true" />
<add key="hibernate.connection.provider" value="NHibernate.Connection.DriverConne
<add key="hibernate.dialect" value="NHibernate.Dialect.MsSql2000Diale
<add key="hibernate.connection.driver_class"
<add key="hibernate.connection.connection_str
</nhibernate>
</configuration>
*********************************
Смотрим все ли совпадает. У мну хибер 1.2.0
В теге
<add key="hibernate.connection.connection_str
Теперь можно создать класс контроллер, который будет позволять нам работать с объектами хибера.
Пример:
****************************************
using NHibernate;
using NHibernate.Cfg;
using WindowsApplication2.Objects;
namespace WindowsApplication2
{
public class DataController
{
private ISessionFactory _sessions;
public DataController()
{
Configuration cfg = new Configuration();
cfg.AddClass(typeof (DataElement));
cfg.AddClass(typeof(Pins));
cfg.AddClass(typeof (WindowsApplication2.Objects.Properties)
cfg.AddClass(typeof(Library));
_sessions = cfg.BuildSessionFactory();
//new SchemaExport(cfg).Create(true, true);//Для создания бд раскоментить
}
public int SaveElement(DataElement el)
{
ISession session = _sessions.OpenSession();
ITransaction tx = null;
try
{
tx = session.BeginTransaction();
int ID = (int)session.Save(el);
tx.Commit();
return ID;
}
catch (HibernateException e)
{
if (tx != null) tx.Rollback();
throw e;
}
finally
{
session.Close();
}
}
}
}
****************************************
Извините за названия сборок.)
Что тут происходит? В конструкторе контроллера мы начинаем конфигурировать хибернейт. И строим сессию исходя из конфига.
Закоменченная строка позволяет создавать БД, исходя из конфига. Мы добавляем наши классы хибера cfg.AddClass(typeof (DataElement)); и так для каждого класса хибера.
Также тут представлен метод сохранения объекта. Работаем с хибером следующем образом:
Открываем сессию. Начинаем транзакцию. Делаем что нам нужно. Подтверждаем транзакцию. Если ошибки, отколоняем транзакцию. И всегда закрываем сессию. Для работы метода передаем хиберовский объект.
Разберемся получше с объектами хибернейта.
Маппинг:
**********************
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="Diplom.Data.Pins,Diplom.Data" table="Pins" lazy="false" >
<id name="Id" column="ID" type="Int32" unsaved-value="0">
<generator class="native"/>
</id>
<property column="X" type="Int32" name="X" />
<property column="Y" type="Int32" name="Y" />
<many-to-one name="FkElement" column="FKElement" class="Diplom.Data.DataElement,Diplom.Da
<property column="Number" type="Int32" name="Number" />
</class>
</hibernate-mapping>
**********************
<id name="Id" column="ID" type="Int32" unsaved-value="0">
<generator class="native"/>
</id>
это описание PK. Name - имя в классе хибера. Column - имя в БД. И выбираем тип генератора. О всех генераторах смотри в доках по хиберу.
<property column="Y" type="Int32" name="Y" /> описание столбца. Тоже самое все.
<many-to-one name="FkElement" column="FKElement" class="Diplom.Data.DataElement,Diplom.Da
В классе объекта хибера, все паблик методы должны быть виртуальными! В маппинге обрати внимание на <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"> Должно быть именно 2.2. в нашей версии хибера.
В маппинге объектов <class name="WindowsApplication2.Objects.DataEl
Так же отмечу что шаблон немного надо подправить будет, который используется в МГ при генерировании объектов. Надеюсь проблем у вас при это не возникнет. Но если надо, могу выложить.
Ну вот в принципе небольшой пример по поводу того как начать быстро работать с хибером. Я рассказывал именно о том как начать быстро работать, а не о том как устроен хибер. Будут вопросы, всегда отвечу.)
Хроники.
30 марта 2008
14:00 Прогулка
Хороший день, славная прогулка с любимой девушкой по городу. Радуемся жизни. Конечно же в кафе зайти обязательно надо! Иначе как же?.. Зашли. Вкусные обед, но очень горячий. Еще чуть чуть зуб побаливал. Но ничего все хорошо!)
19:00 Дом
Хорошо дома!) Девушка под боком. Сейчас будем готовить ужин. Но что то зуб болит... Лана, пройдет.
22:00 Дом
Поели горяченького. Хорошо!)) Но вот зуб что то совсем разболелся. Уже очень неприятно...
31 марта 2008
2:00 Кровать
Эта жуткая боль разламывает весь мой череп! Невозможно спать! Невозможно сидеть, лежать, ходить! Она просто пробивает мозг! Пью Кетанов. Нифига! Еще пью! Боль утихает, но спать невозможно!((
09:00
Звоню дантистам, записываюсь на прием! Невозможно так жить! Боль поглащает! На работу не иду! На два часа записываюсь к врачу на прием.
14:00 Стоматология
Делают снимок. Какая то дрянь на снимке возле кончика корня. Здоровые две плямбы... Говорят зубу хана. Надо удалять...((( Мда... Чудесно... Завтра удаление. Но как еще прожить ночь?????
21:00 дом
Просидел дома... Невозможно жить. Кетанов пьется пачками. Ждем завтра.
1 апреля 2008
13:00 Стоматология
Ну вот я и в кресле. За ночь Появилась опухоль. Зуб болит меньше. Но теперь раздулась щека. Жесть... Врач делает еще снимок. Ворчит на меня. Где мол ходил то так долго?.. Мда. Берет шприц. Ставит укол, анестезия мать ее... Уколов я не то что бы боюсь, но опасаюсь. Ну делать нечего... Вот он ставит его... В язык ударяет резкая боль, словно залили расплавленный метал! Жесть! Через 10 сек все проходит. Еще через 5 минут я уже ничего не чувствую. Еще несколько уколов, ощущений никаких вообще. Норм.
13:15 Стоматология
Ну вот зуб удален. Теперь будут опухоль снимать. Пока зуб удаляли, не почувствовал вообще ничего. Ток неприятные звуки... Норм. Но вот он говорит что надо снимать опухоль.Ну лана думаю. Но после слова скальпель я напрягся.) Порезал он там что то, вставил резинку и все. Боль была, но терпимая. Все. Вставай говорит и топай.)) Ток ща напишу что тебе делать дальше...
7 апреля 2008
9:00 дом
Проснулся подошел к зеркалу.Опухоль на щеке почти не видно. Зуба нет. Все нормально.) Мда. Опухоль спадала долго. Почти неделю. В первый и второй день после удаления была температура. Почти 39. Не сбивалась. Думал все... Но ничего. Потом стало лучше. Полоскал содой и солью всю неделю рот. Пил какие то антибиотики. Боль была уже совсем не та. Хотя пару раз выпил кетанов. Все таки удалять зуб не больно. Больнее ходить с ним, больным...
30 марта 2008
14:00 Прогулка
Хороший день, славная прогулка с любимой девушкой по городу. Радуемся жизни. Конечно же в кафе зайти обязательно надо! Иначе как же?.. Зашли. Вкусные обед, но очень горячий. Еще чуть чуть зуб побаливал. Но ничего все хорошо!)
19:00 Дом
Хорошо дома!) Девушка под боком. Сейчас будем готовить ужин. Но что то зуб болит... Лана, пройдет.
22:00 Дом
Поели горяченького. Хорошо!)) Но вот зуб что то совсем разболелся. Уже очень неприятно...
31 марта 2008
2:00 Кровать
Эта жуткая боль разламывает весь мой череп! Невозможно спать! Невозможно сидеть, лежать, ходить! Она просто пробивает мозг! Пью Кетанов. Нифига! Еще пью! Боль утихает, но спать невозможно!((
09:00
Звоню дантистам, записываюсь на прием! Невозможно так жить! Боль поглащает! На работу не иду! На два часа записываюсь к врачу на прием.
14:00 Стоматология
Делают снимок. Какая то дрянь на снимке возле кончика корня. Здоровые две плямбы... Говорят зубу хана. Надо удалять...((( Мда... Чудесно... Завтра удаление. Но как еще прожить ночь?????
21:00 дом
Просидел дома... Невозможно жить. Кетанов пьется пачками. Ждем завтра.
1 апреля 2008
13:00 Стоматология
Ну вот я и в кресле. За ночь Появилась опухоль. Зуб болит меньше. Но теперь раздулась щека. Жесть... Врач делает еще снимок. Ворчит на меня. Где мол ходил то так долго?.. Мда. Берет шприц. Ставит укол, анестезия мать ее... Уколов я не то что бы боюсь, но опасаюсь. Ну делать нечего... Вот он ставит его... В язык ударяет резкая боль, словно залили расплавленный метал! Жесть! Через 10 сек все проходит. Еще через 5 минут я уже ничего не чувствую. Еще несколько уколов, ощущений никаких вообще. Норм.
13:15 Стоматология
Ну вот зуб удален. Теперь будут опухоль снимать. Пока зуб удаляли, не почувствовал вообще ничего. Ток неприятные звуки... Норм. Но вот он говорит что надо снимать опухоль.Ну лана думаю. Но после слова скальпель я напрягся.) Порезал он там что то, вставил резинку и все. Боль была, но терпимая. Все. Вставай говорит и топай.)) Ток ща напишу что тебе делать дальше...
7 апреля 2008
9:00 дом
Проснулся подошел к зеркалу.Опухоль на щеке почти не видно. Зуба нет. Все нормально.) Мда. Опухоль спадала долго. Почти неделю. В первый и второй день после удаления была температура. Почти 39. Не сбивалась. Думал все... Но ничего. Потом стало лучше. Полоскал содой и солью всю неделю рот. Пил какие то антибиотики. Боль была уже совсем не та. Хотя пару раз выпил кетанов. Все таки удалять зуб не больно. Больнее ходить с ним, больным...
Извиние за задержку. На выходных написал програму, а саму статью еще не закончил. Скоро все будет.)
Всем привет. Решил вот начать вести свой журнал... Хочу написать пару статей. Может быть у кого нибудь будут пожелания?? Статьи будут для новичков, что бы можно было въехать в кое какие аспекты программирования. Хотя возможно буду рассказывать о программировании на C# и все что с этим связано. Потихоньку, будем писать и разбираться. Я еще подумаю. Вообе почему я решил вести такой цикл? Потому что я студент и прекрасно понимаю как идет образование в наших вузах. Где остаются затронуты лишь верха нашей сложной работы. А мы будем постепенно вникать глубже.
Жду комментариев. :-)
Жду комментариев. :-)
- Location:На работе...
