Интернет системы

Автор работы: Пользователь скрыл имя, 30 Января 2013 в 03:08, курсовая работа

Описание

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

Работа состоит из  1 файл

Документ Microsoft Office Word.docx

— 74.53 Кб (Скачать документ)

 

Кроме того, при работе с CachedUpdates (если вам вообще нужен режим CachedUpdates) необходимо тщательно следить за порядком отправки записей на сервер (как в пункте 7 обращено внимание на порядок создания компонент) - вначале  должна идти запись master, и только затем - detail. Для этого нужно вызывать методы ApplyUpdates соответствующих компонент  в правильном порядке (а не вызывать IBDatabase.ApplyUpdates, т.к. в этом случае правильный порядок может быть не соблюден).

Locate (поиск)

 

В выбранных IBDataSet (IBQuery) записях  можно производить поиск вызывая метод Locate. Поскольку запрос, выбирающий записи, указан явно в SelectSQL, компонент не может сделать ничего другого как по очереди перебирать выбранные записи от начала до конца (от First до EOF, путем вызова Next), и производить поиск в буфере. Если IBDataSet был только что открыт, и FetchAll не вызывался, то вызов Locate приведет к выборке на клиента (в локальный буфер) всех записей, возвращаемых запросом.

Работа с BLOB

 

Ничего сложного. В IBX это  делается следующим образом 

(то же самое - и в  FIBPlus. см. статью http://www.devrace.com/ru/fibplus/articles/2261.php)

procedure TForm1.Button1Click(Sender: TObject);

begin

  IBDataSet1.FieldByName('BLB') as TBlobField).SaveToFile('c:\blob.bin');

  ...

 

end;

 

Практически то же самое - при записи, причем делать это можно двумя вариантами:

 

1. передача blob через параметр. Имеется в виду запрос вида

insert into table (field1, field2, blbfield) values (:param1, :param2, :blb); :

 IBQuery1.ParamByName('blb').asBlob:=blobvar;

 

asBlob принимает значение  в виде простой строки (string). Действительно,  строки в последних версиях  Delphi (как минимум с Delphi 3) могут  содержать любую, в т.ч. двоичную  информацию. Поэтому значение параметру  blob можно присваивать и как  asString.

 

2. изменение столбца "редактируемого" DataSet - запись blob из файла в столбец:

 IBDataSet1.Edit;

(IBDataSet1.FieldByName('BLB') as TBlobField).LoadFromFile('c:\blob.bin');

 IBDataSet1.Post;

 

В предыдущих версиях IBX (до 4.42 включительно) можно было работать с blob иначе. Например, запись в файл

procedure TForm1.Button1Click(Sender: TObject); 

var B: TIBBlobStream; 

begin   

  B:=IBDataSet1.CreateBlobStream(IBDataSet1.FieldByName('BLB') as TBlobField, bmRead);   

  B.SaveToFile('c:\blob.bin');   

  B.Free; 

end;

 

и чтение из файла 

  IBDataSet1.Edit;  

  B:=IBDataSet1.CreateBlobStream(IBDataSet1.FieldByName('BLB') as TBlobField, bmWrite);  

  B.LoadFromFile('c:\blob.bin');  

  B.Free;  

  IBDataSet1.Post;

 

Обратите внимание, что  метод B.Free вызывается перед вызовом IBDataSet1.Post (а не наоборот, как это  приведено в некоторых старых примерах в интернете).

JPEG в Blob

 

Какой формат хранить в Blob - абсолютно неважно. Компоненты IBX и Interbase/Firebird никак не реагируют на содержимое Blob - они его не анализируют, не отображают, не конвертируют и т.п.. Если у вас есть проблемы с отображением Jpeg, хранимого в blob, обратитесь к поисковым серверам в интернете - вы за 1 минуту сможете найти несколько вариантов DBImage, который корректно работает с Jpeg и другими форматами. Еще раз подчеркиваю, что любые проблемы с форматом содержимого blob не относятся к IBX, FIBPlus, любым другим драйверам, и к серверам InterBase, Firebird или Yaffil.

Blob и DBGrid

 

Стандартный DBGrid не показывает в строке содержимое blob. Различные сторонние варианты DBGrid могут отображать - наличие-отсутствие данных в blob, значение blob в виде hint, в виде строки, в виде картинки и т.п. Практически все эти способы являются малоэффективными с точки зрения визуализации данных, и на самом деле производят серьезную нагрузку на сеть из-за перекачивания всех столбцов blob с сервера на клиента.

 

Blob-данные в записях  не хранятся. То есть, в записи (столбце) на самом деле находится  ссылка на blob. И клиентская часть  извлекает с сервера сначала  записи, и только потом, если  клиентские компоненты это делают, при помощи специальных вызовов  по идентификатору blob он выбирается  с сервера. То есть, даже если  в записи есть blob-столбцы, то  их выборка - дело совершенно  необязательное.

 

Если перед вами стоит  задача отображения информации вроде  записей отдела кадров, где к записи о работнике могут быть прицеплены следующие (и иногда весьма объемные) данные - автобиография, резюме, фотография 3x4, фотография 9x12, договор, и т.п.

 

Допустим, в IBDataSet или IBQuery вы написали запрос select * from personinfo. Стандартный DBGrid, как уже говорилось, никак не умеет выводить содержимое столбцов blob. Поэтому blob-ы при выполнении данного запроса не будут считываться с сервера. Если же DBGrid показывает blob-ы в том или ином виде, то соответственно, все блобы из вместившихся в DBGrid записей будут считаны на клиента. Возможно, что более эффективным способом было бы вместо select * написать select с перечислением только тех столбцов, которые действительно нужны, а затем, при выборе нужной записи, показывать содержимое столбцов blob либо автоматически, по таймеру, либо по нажатию специальной кнопки (на этой же форме или в отдельной, как угодно), отдельным запросом

 

select blob1, blob2, blob3 from table where pk_field = :param

 

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

 

примечание: "по таймеру, ..." - имеется в виду следующий механизм: на форму с DataSet/DataSource кладется TTimer, у которого выставляется интервал срабатывания в 800 (0.8 секунды, зависит от квалификации пользователя программы). TTimer постоянно  сбрасывается и взводится снова  в событии DataSource.onDataChange (для режима просмотра записей, dsBrowse). По истечению  таймера (TTimer.OnTimer), если в DataSet есть записи, у текущей записи берется значение столбца первичного ключа, выполняется  вышеупомянутый запрос, и компоненты Memo, Picture и т.п. заполняются данными, считанными этим дополнительным запросом.

IBTable

TIBTable = class(TIBCustomDataSet)

 

В общем случае - заменитель компонента TTable, для облегчения перехода с BDE (как и IBQuery). Для работы требует  указания имени таблицы, после чего запрос на считывание данных формируется  автоматически.

 

Важные свойства

TableName - имя таблицы

TableTypes - типы таблиц, отображаемые  в выпадающем списке TableName - ttSystem включает выборку системных таблиц (rdb$, tmp$), а ttView - включает выборку  VIEW.

IndexName - имя индекса для  сортировки. Так же, как и в  BDE, имя индекса используется косвенно, для получения столбцов индекса,  и добавления фразы ORDER BY INDEXFIELD1, INDEXFIELD2 к автоматически конструируемому  запросу. Поэтому для сортировки  по любому столбцу, даже непроиндексированному,  следует использовать свойство IndexFieldNames.

Явно сортировку записей  в обратном порядке (DESC) указать невозможно.

Filter - условие фильтрации. Текст свойства Filter добавляется как условие where к автоматически конструируемому запросу.

 

Поскольку свойство ReadOnly по умолчанию False, IBTable сразу готов к  редактированию данных - поскольку  запрос на чтение формируется из одной  таблицы, то запросы insert/update/delete могут  быть легко сформированы автоматически. Сортировка записей по умолчанию (order by) производится по столбцам первичного ключа (primary key).

Locate

 

Для IBTable Locate производит поиск  несколько иначе, чем например для IBQuery. Условия поиска раскладываются в соответствующую конструкцию where, после чего выполняется запрос. Если такие записи найдены, то поиск производится вызовом IBCustomDataSet.Locate (аналогично IBDataSet, IBQuery). Если записи не найдены, поиск  в буферизированных записях не производится.

Почему компонент IBTable не рекомендуют?

 

Действительно, на многих форумах  использование IBTable не рекомендуют  и считают "ламерским". Дело в  том, что как уже было сказано  выше, IBTable формирует SQL-запросы к  БД самостоятельно. А это при работе с SQL-серверами считается некорректным. Т.е. запросы необходимо контролировать, для того чтобы знать, что именно делается для выборки данных. Более  того, часто IBTable используют для выборки  из таблиц с большим числом записей, что также отрицательно влияет на производительность сервера и приложения.

 

В основном, конечно, негативное отношение к IBTable базируется на аналогичном  отношении к его "родителю", компоненту TTable, который мог приводить  к серьезным проблемам с производительностью  приложений.

 

Итак - TTable предназначен для имитации "навигационного" доступа, к которому привыкли пользователи десктопных СУБД, и плох для SQL-сервера. IBTable наследует его характеристики, и предназначен для облегчения переноса приложений BDE на компоненты IBX. Тем не менее, иногда удобно использовать IBTable для осуществления доступа к справочникам.

 

Помните, что изначально в  компонентах FreeIBDatabase никакого IBTable не было. Был только один компонент, который позволял работать с набором данных - IBDataSet. И уже от него произошли и IBQuery, и IBTable.

IBQuery

TIBQuery = class(TIBCustomDataSet)

 

Компонент для выполнения запросов. Если не требуется выполнять "редактирование" записей запроса, то IBQuery можно использовать вместо IBDataSet. Или, как замену IBDataSet можно использовать комбинацию IBQuery + IBUpdateSQL.

 

Дополнительно к свойствам IBDataSet (кроме отсутствующих Refresh/Insert/Update/DeleteSQL) имеет свойство Constraints (отсутствие данного  свойства у IBDataSet скорее связано с какими то недоделками, т.к. компоненты IBTable, IBQuery и IBDataSet - унаследованы от IBCustomDataSet).

 

Для запросов, возвращающих набор записей, можно установить свойство Active в True или вызвать метод Open. Для остальных запросов, таких  как insert/update/delete, execute или операторов DDL (create table, alter, drop...) нужно вызывать метод ExecQuery, т.к. эти запросы не возвращают записи, а возвращают только результат  выполнения оператора SQL.

 

Помните, что IBQuery при выполнении запросов SELECT буферизирует записи точно  так же, как и IBDataSet. Если необходимо просто перебрать записи, или экспортировать их в файл или другую СУБД - используйте  небуферизирующий компонент IBSQL.

 

! для выполнения процедур, возвращающих данные (execute procedure) следует  использовать IBSQL или IBStoredProc, т.к.  вызов IBQuery.ExecSQL не заполняет Fields данными, полученными от процедуры. 

Параметризированные запросы

 

Компоненты IBDataSet, IBQuery и IBSQL могут  выполнять как статический, так  и динамический SQL. Динамический SQL отличается от статического наличием параметров. Пример статического SQL:

select * from table

 where field > 5

 

Если вместо цифры 5 предполагается использовать значение, полученное как  ввод данных пользователем, то следует  использовать параметризированный  запрос (ParamCheck:=True):

select * from table

 where field > :param

 

Двоеточие или символ '?' означают, что запрос предполагает задание  параметра. Делается это следующим  образом:

IBQuery.SQL.Clear; // очистить текст  sql

IBQuery.SQL.Add('select * from table where field > :param'); // задать текст запроса

IBQuery.Prepare;   // отправить  запрос на сервер, проверить его  корректность и т.п.

IBQuery.ParamByName('param').asInteger:=5; // задать  значение параметра

IBQuery.Open;      // или  IBQuery.ExecSQL

 

Для статических запросов вызов Prepare необязателен - компонент  сам его выполнит автоматически, если Prepare не был вызван.

 

примечание: после Prepare можно  обратиться к свойству Plan, т.к. именно после Prepare сервер сообщает план выполнения запроса.

 

Prepare очень удобен при повторяющемся выполнении одного и того же запроса, с разными значениями параметра. При этом Prepare вызывается один раз, а установка параметров и вызов ExecQuery производится столько раз, сколько нужно. Чаще всего такой способ используется для запросов Insert и Update.

 

! имена параметров поддерживаются  только клиентской библиотекой.  То есть, сервер понимает параметры  только в виде символа '?'. Если  компоненты умеют обрабатывать  именованные параметры, то они  перед отправкой запроса на  сервер "вырезают" их, отправляя  туда запрос вида 

select * from table

 where field > ?

 

Некоторые библиотеки компонент  могут не поддерживать или некорректно  обрабатывать запросы, в которых  используется два или более параметров с одинаковым именем.

Фильтрация

 

Возможно, в BDE или ином используемом вами до IBX наборе компонент доступа  к БД вы активно применяли фильтрацию записей. В общем фильтрация в IBX работает практически так же, как и в BDE.

IBTable

 

Для этого компонента в  свойстве Filter должны быть описаны условия  фильтрации так, как будто вы добавляете условие where к обычному запросу SQL. IBTable сконструирует запрос, используя  заданное в TableName имя таблицы, добавит  как where условие фильтрации из Filter, и  добавит конструкцию ORDER BY если указана "сортировка" результирующего набора при помощи свойств IndexFieldNames или IndexName.

Поэтому, в Filter должен быть указан текст с учетом всех особенностей синтаксиса InterBase или Firelbird. Например

LasName like  'A%'

 

В итоге запрос, отсылаемый на сервер, будет иметь вид

select id, LastName, FirstName...

from TABLE

where LastName like 'A%'    

IBDataSet, IBQuery

 

Эти компоненты выполняют  запросы, четко заданные в свойствах SelectSQL или SQL. Поэтому дополнительная фильтрация возможна только методом OnFilterRecord.

OnFilterRecord

 

Компоненты IBTable, IBDataSet и IBQuery позволяют использовать это событие  для фильтрации записей. В отличие  от IBTable, где в свойстве Filter можно  указать дополнительное условие  отбора для запроса, выполняемого на сервере, OnFilterRecord определяет "видимость" записи, уже принятой DataSet-ом с сервера. Метод имеет два параметра - DataSet, то есть что за компонент запросил фильтрацию (для возможности получения  данных из "текущей" записи), и Accept, который определяет, показывать данную запись подключенному компоненту DataSource или нет. Для того, чтобы имитировать фильтрацию, показанную выше на примере для IBTable, в OnFilterRecord нужно написать примерно следующее:

Accept:=(DataSet.FieldByName('LastName').asString >= 'A') and

        (DataSet.FieldByName('LastName').asString <  'B');

 

Помните, что фильтрация производится в локальном буфере уже принятых с сервера записей. То есть, если в программе предполагается небольшое  число вариантов фильтрации, то возможно, имеет смысл уменьшить нагрузку на клиентскую часть и при изменении  фильтра конструировать запрос для SelectSQL с нужным условием where (точно так же как это делает IBTable, только строку where вы будете добавлять к тексту запроса самостоятельно).

IBUpdateSQL

 

Компонент для "оживления" IBQuery. То есть, комбинация IBQuery + IBUpdateSQL представляет собой аналог IBDataSet. Для работы такой  связки не требуется включение режима CachedUpdates, как это требовалось в BDE.

IBUpdateSQLW

 

В поставке такого компонента нет. Зато он есть здесь. Он предназначен для выполнения операторов Select/refresh и insert/update/delete в разных транзакциях. Зачем это нужно, см. дальше информацию по транзакциям в приложении.

Информация о работе Интернет системы