Автор работы: Пользователь скрыл имя, 30 Января 2013 в 03:08, курсовая работа
Методологической и теоретической основой исследования послужили работы зарубежных и российских авторов в области бизнес-планироания, менеджмента и маркетинга, связанные с тематикой работы.
Информационную основу исследования составили маркетинговые исследования, проводимые российскими консалтинговыми компаниями, работающими на рынке недвижимости, а также данные, полученные в ходе исследования деятельности конкурентов.
В качестве инструментов исследования были использованы сравнительный и системный анализ, качественное и количественное изучение реальности, экономико-статистические методы.
Практическое значимость предложенных рекомендаций заключается в том, что их использование позволит создаваемому агентству недвижимости успешно выйти на рынок недвижимости Москвы.
Кроме того, при работе с 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/
procedure TForm1.Button1Click(Sender: TObject);
begin
IBDataSet1.FieldByName('BLB') as TBlobField).SaveToFile('c:\
...
end;
Практически то же самое - при записи, причем делать это можно двумя вариантами:
1. передача blob через параметр. Имеется в виду запрос вида
insert into table (field1, field2, blbfield) values (:param1, :param2, :blb); :
IBQuery1.ParamByName('blb').
asBlob принимает значение
в виде простой строки (string). Действительно,
строки в последних версиях
Delphi (как минимум с Delphi 3) могут
содержать любую, в т.ч.
2. изменение столбца "
IBDataSet1.Edit;
(IBDataSet1.FieldByName('BLB') as TBlobField).LoadFromFile('c:\
IBDataSet1.Post;
В предыдущих версиях IBX (до 4.42 включительно) можно было работать с blob иначе. Например, запись в файл
procedure TForm1.Button1Click(Sender: TObject);
var B: TIBBlobStream;
begin
B:=IBDataSet1.
B.SaveToFile('c:\blob.bin');
B.Free;
end;
и чтение из файла
IBDataSet1.Edit;
B:=IBDataSet1.
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-данные в записях
не хранятся. То есть, в записи
(столбце) на самом деле
Если перед вами стоит задача отображения информации вроде записей отдела кадров, где к записи о работнике могут быть прицеплены следующие (и иногда весьма объемные) данные - автобиография, резюме, фотография 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
включает выборку системных
IndexName - имя индекса для
сортировки. Так же, как и в
BDE, имя индекса используется
Явно сортировку записей в обратном порядке (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 базируется на аналогичном
отношении к его "родителю",
компоненту 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/
Для запросов, возвращающих набор записей, можно установить свойство 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').
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('
(DataSet.FieldByName('
Помните, что фильтрация производится в локальном буфере уже принятых с сервера записей. То есть, если в программе предполагается небольшое число вариантов фильтрации, то возможно, имеет смысл уменьшить нагрузку на клиентскую часть и при изменении фильтра конструировать запрос для SelectSQL с нужным условием where (точно так же как это делает IBTable, только строку where вы будете добавлять к тексту запроса самостоятельно).
IBUpdateSQL
Компонент для "оживления" IBQuery. То есть, комбинация IBQuery + IBUpdateSQL представляет собой аналог IBDataSet. Для работы такой связки не требуется включение режима CachedUpdates, как это требовалось в BDE.
IBUpdateSQLW
В поставке такого компонента нет. Зато он есть здесь. Он предназначен для выполнения операторов Select/refresh и insert/update/delete в разных транзакциях. Зачем это нужно, см. дальше информацию по транзакциям в приложении.