Rambler's Top100
Главная
Новости
Статьи
Форумы
Книги
Коды
Сообщество
Блоги
О нас
 

Логин

Email:
  Пароль:

Войти
Зарегистрироваться
Забыл пароль

Поиск

 Искать :
 
Вперед

Активные блоггеры

 clevelus (1)
 Devel (2)
 RredCat (1)
 GreenAsh (2)
 Vladimir (1)
 advanta-group (1)
 Sheba (2)
 tsagi (1)
 m-jodo (1)
 siteman07 (3)
 Reg-Su.Ru (1)
 dmitry39 (4)
 IVAN (2)
 armex (3)
 natalia (1)
 чиин (1)
 Ivinsky (1)
 alekra (1)
 iwd (1)
 gst (1)

 | 

Nik Legaloff Blog.

Thursday, August 11, 2005

Сессия работы с данными

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

Пишла в голову идея, реализацией которой я давно пользуюсь. Сча решил ей поделиться.

Для чего нужна такая сессия?
1. В ней удобно хранить свой connectionManager, который будет раздавать соединения именно для этого клиента.

2. Её легко по событию OnUnload(перегрузить его в своём базовом типе страницы) или по Application_EndRequest можно закрывать и не бояться забыть это сделать явно. При закрытии можно высвобождать занятые ресурсы(если их учёт ведёт обьект, лежащий в датаСессии) можно камитить по умолчанию все бизенес транзакции.

3. Там же место экземпляру UnitOfWork и IdentityMap

4. Она может быть легкодоступна (DataSession.Current.)

Реализация проста.
Статическое поле - hashtable в котором лежат сами сессии, а key у элемента hashtable - любой уникальный идентификатор клиента(в самом простом случае идентификатор сессии, но можно реализовать и свой механизм)
2 статических метода.
1. Получить экземпляр текущей сесии(если таковой отсутсвует - создать новый)
2. Закрыть текущую сессию( и удалить её из коллекции)

ну а в самом класе datasesion ложим экземпляры нужных обьектов и делаем к ним проперти. Если используем бизнесТранзакцию то реализуем свои методы, типа Commit(), Rollback()
Кстати удачно получается реализация Rollback, при этом просто сбрасывается UnitOfWork и очищается IdentityMap. Опля, и все действия забытыУлыбка

пример реализации Сессия работы с данными для web

ЗЫ. Не стоит забывать что вышесказанное эффективно только для webApp. для winApp совсем другая история.

Nik Legaloff

11 August 2005 19:15  Комментарии (13)

Wednesday, August 10, 2005

Connection managment

У всех своя стратегия управления соединениями.
Хочу поделиться своей.
Предпосылки
1. Web приложение
2. За время жизни формы на сервере часто нужны новые соединения.
3. Часто бывает что пока открыто одно соединение, и из него читаются данные, необходимо открывать другие соединения.
4. Допустим что приложение работает пока только с одной БД(один connectionString)

Самое простое решение - каждый раз открывать новое соединение.
ВОт пример.
public static SqlConnection GetNewConnection()
{
// просто каждый раз создаём новое соединение
SqlConnection conection = new SqlConnection(CStr);
return conection;
}
где CStr это кэшируемый connectionString взятый к примеру из config файла


/// <summary>
/// ConnectionString для текущего приложения указанный config файле
/// </summary>
public static string CStr
{
get
{

lock(cstrLock)
{
try
{
if (cstr == null)
{
AppSettingsReader reader = new AppSettingsReader();
cstr = reader.GetValue("ConnectionString", typeof(string)).ToString();
}
}
catch
{
cstr = "connection string по умолчанию";

}
return cstr;
}


}
}


т.е. просто взяли новый connection, поюзали, да главное не забыли его потом закрыть.

Аднака хоть соединения не создаются каждый раз по новой, а берутся из connectionPool которого нам не видно, но всё же это происходит долго.
Пример моей статистики. несколько десятков запросов, каждый создаёт соединение.
половина времени лежала на открытии нового соединения.

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

реализацию можно увидеть в примере кода

ЗЫ. Хранить экземпляр ConnectionPool можно в любом легкодоступном месте.
Я например его храню в DataSession(аналог Session). Это статическая коллекция экземпляров DataSession, каждый из которых привязывается к сессии клиента.
К тому же там удобно хранить экземпляр UnitOfWork или IdentityMap.
Ну нужно не забывать по окончанию реквеста их всех закрывать. Клиент то может не вернуться. Но это уже совсем другая история

Nik Legaloff

10 August 2005 19:27  Комментарии (10)

Tuesday, August 09, 2005

Биндим грид коллекцией своих обьектов.

Давно отказался я в вебе от датасетов. Да вот засада, когда биндишь тот же ArrayList коллекцией обьектов своего типа, дизайнер никак не подсказывает имена пропертей. Вчера пришла в голову идея, чуть позже появилась её первая реализация.
Идея состояла в том, что бы подсовывать гриду в качестве датасорса свой компонент. А в нём можно в дизайн-тайме подсовывать гриду подготовленный датасет, а в рантайме данные можно брать у делегированного метода(заодно и красиво выносится в отдельный метод выборка данных для грида).

Итак.
Есть у нас к примеру класс Employee, а точней MyApp.Domain.Employee
Находится он к примеру в сборке "MyAppDomain"

Дизайн-тайм. Дизайнер выбирает данные из компонента по интерфейсу IListSource, а точней по его методу IList GetList()
Для него мы создадим датасет и туда добавим табличку с именем "MyApp.Domain.Employee"
После загружаем сборку MyAppDomain и находим там тип MyApp.Domain.Employee
Пробежимся по нему рефлектором и добавим в DataTable колонки с именем property.Name и типом property.PropertyType

всё, теперь можно в GetList возвращать dataSet.DefaultViewManager

Ран-тайм.
Ну а тут наш компонент возвращает данные через IEnumerable, который он и реализует. Использующий нас класс должен реализовать ивент
public event IListHandler GetEnumerableData; который вернёт нам IEnumerable коллекцию.
её то мы и вернём
public IEnumerator GetEnumerator()
{
return GetEnumerableData().GetEnumerator();
}

Ну вот собссно и всё.
Исходники здесь

ЗЫ. Небольшая поправка. На самом деле надо переименовать делегат IListHandler в IEnumerableSourceHandler. Так будет правильней, просто в первоначальном варианте я немного иначе извлекал данные для грида в ран-тайм.

Nik Legaloff

09 August 2005 13:20  Комментарии (7)

 
Наш Киев

Apartments for Rent

Rambler's Top100
Рейтинг@Mail.ru
Идея: Dimon aka Manowar Программирование: Dimon aka Manowar Дизайн: Dan Lebedev
Хостинг от компании Parking.ru
Карта сайта