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

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

Описание

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

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

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

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

 

В приложении можно использовать сколько угодно компонентов TIBTransaction. Худшими случаями являются как один компонент на все приложение (пример ibmastapp из Delphi), так и по компоненту на каждый выполняемый запрос. Вы должны определить сами, сколько вам нужно  экземпляров TIBTransaction, в соответствии с задачами вашего приложения.

 

! В коде не рекомендуется  для старта или завершения  транзакции использовать property Active - явный вызов методов StartTransaction, Commit и Rollback отлично самодокументирует  приложение, может быть найден  поиском, и кроме того, Active:=False завершит транзакцию безусловным  вызовом Rollback.

 

Для работы в режиме "только чтение" (например со справочниками  или при использовании с "двутранзакционными" датасетами, т.е. раздельными транзакциями для чтения и записи) в FB 1.x и IB 7.x рекомендуется  использовать параметры

 

read

read_committed

rec_version

 

такая транзакция в InterBase 6.0 и  выше (все версии IB 7.0, 7.1, 7.5, Firebird и Yaffil) может быть открытой сколь угодно долгое время (дни, недели, месяцы), без  блокирования других транзакций или  влияния на накопление мусора в базе данных (потому что на самом деле на сервере такая транзакция стартует как committed). Однако, такая транзакция (read_committed) во время перечитывания данных будет видеть все новые committed-изменения, и например, для отчетов, ее использовать нельзя. Более подробно о параметрах транзакций см. документ.

 

Подробнее об управлении транзакциями см. раздел "Использование и управление IBTransaction в приложениях"

Датасеты

 

Работать с данными  в IBX можно при помощи компонент IBDataSet, IBQuery, IBTable, IBStoredProc, IBSQL, но IBSQL не является датасетом, а IBStoredProc хоть и является датасетом, получать из него выборки  невозможно (см. далее).

 

TIBDataSet, TIBQuery, IBTable, TIBStoredProc унаследованы  от TIBCustomDataSet.

IBDataSet

TIBDataSet = class(TIBCustomDataSet)

 

Основной компонент, пришедший  из FreeIBComponents. Остальные, то есть IBTable, IBQuery (+IBUpdateSQL) - всего лишь модификации, либо чуть расширенные, либо усеченные. Возможностей этого компонента хватает практически  для любых целей.

 

Назначение компонента - буферизация  записей, выбираемых оператором SELECT, для  представления этих данных в Grid, а  также для обеспечения "редактируемости" записи (текущей в буфере (гриде)) путем автоматического или ручного  задания запросов Insert, Delete и Update.

 

! для выполнения отдельных  запросов insert, update, delete, execute procedure и операторов DDL вместо IBDataSet следует использовать IBQuery или IBSQL.

 

Основные свойства:

BufferChunks - размер буфера (число  записей), аллокируемого IBDataSet-ом  за 1 раз. 

Database - связь с компонентом  IBDatabase

DataSource - ссылка на Master-источник  данных (TDataSource) для IBDataSet, используемого в качестве Detail.

ForcedRefresh - при False перечитывание  данных (текущей записи) производится  только при явном вызове Refresh. При True - происходит автоматически  при Post. Вызов метода Refresh будет  перечитывать только одну, текущую  запись. Для перечитывания всего  набора нужно закрыть и открыть  датасет, то есть повторно выполнить  запрос, хранимый в свойстве SelectSQL (дальше).

GeneratorField - по нажатию на  кнопке ... выводится диалог для  конфигурирования "автоинкремента" - какому столбцу, какой генератор, с каким шагом, и по какому действию (onNewRecord, onPost, onServer). Это автоматический вызов инкремента значения генератора и помещения его в столбец, вместо ручного использования генераторов.

ParamCheck - проверять или нет  наличие в запросе параметров (:param). По умолчанию True. Для выполнения  операторов DDL (create procedure, alter, drop и т.п.) нужно выставить в False.

Transaction - к какой транзакции  привязан компонент.

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

UpdateObject - свойство для подключения  IBUpdateSQL, не нужно.

Запросы:

SelectSQL - основной запрос, который  возвращает данные.

RefreshSQL - запрос для обновления  текущей строки. Должен содержать  условие отбора по первичному  ключу или подобное, для выборки  одной записи.

InsertSQL - запрос для вставки  записи

UpdateSQL - запрос для обновления  записи

DeleteSQL - запрос для удаления  записи

 

Для активации IBDataSet необходимо выполнить ряд действий:

Соединить его с нужным IBDatabase, и с IBTransaction (если это не тот IBTransaction, который указан для IBDatabase.DefaultTransaction).

Определить запрос, выбирающий данные. В этот момент подсоединенные IBDatabase и IBTransaction должны быть активны. Запрос можно указать 

щелкнув на кнопку ... свойства SelectSQL

нажав на компоненте правую кнопку, выбрать в меню Edit SQL

 

Если редактирования данных, возвращаемых запросом SelectSQL, не предполагается, то на этом можно остановиться - после Active:=True компонент выберет данные (которые будут видны, если к IBDataSet уже подсоединены TDataSource и TDBGrid). Иначе  можно задать запросы Insert/Update/Delete/Refresh. Это можно сделать вручную (прописав запрос в окне, выводимом по кнопке ... у конкретного свойства), или  автоматически. Нажмите на IBDataSet правую кнопку, выберите DataSet Editor. Появится диалоговое окно. Базовая информация (имя таблицы, столбцы), уже получена из Select SQL. В  диалоге нужно указать столбцы  первичного ключа (key fields) и обновляемые  столбцы (update fields). Как правило, столбцы  первичного ключа не обновляются, поэтому  их исключают из Update Fields. Теперь можно  нажать Generate SQL. Появится диалоговое окно с переключателями 4-х запросов, сгенерированными автоматически.

 

RefreshSQL - как было сказано  выше, для считывания (перечитывания)  одной записи (текущей в гриде,  например).

 

InsertSQL - для вставки записи. Если столбцы первичного ключа  не указаны в Update Fields, то они  не попадут и в сгенерированный оператор SQL. То есть, нужно отредактировать этот запрос, добавив столбцы первичного ключа в оператор Insert (если только столбцы первичного ключа не заполняются на сервере, что делается редко, и также делает невозможным перечитывание этих данных после вставки).

 

DeleteSQL - для удаления текущей  записи. Условия отбора в where должны  совпадать с RefreshSQL.

 

UpdateSQL - для обновления  текущей записи. Если столбцы  первичного ключа не исключены  из Update Fields, то они будут упомянуты  в update set field =:field, и соответственно  могут обновляться. Изменение  значений столбцов первичных  ключей - нехорошая операция, поэтому  даже если на самом деле  эти столбцы не меняются, их  упоминание надо убрать из set данного  оператора (но разумеется, оставить в where).

 

У IBDataSet есть специальные  параметры, которые могут быть использованы в запросах. Параметры именуются  автоматически, и соответствуют  именам столбцов, предваряемые префиксами old_ и new_. Например - old_client_name, new_client_name. В old_-столбцах хранятся данные текущего столбца до модификации записи, а  в new_ - те, которые ввел пользователь при редактировании.

 

простой пример:

допустим, есть таблица 

create table X(

 id int not null,

 name varchar(30),

constraint PK_X primary key (id))

 

тогда:

SelectSQL = select * from X

InsertSQL = insert into X (id, name) values (:ID, :NAME)

ModifySQL = update X set NAME = :NAME where ID = :OLD_ID

DeleteSQL = delete from X where ID = :OLD_ID

RefreshSQL = Select ID, NAME from X where ID = :ID

 

Обратите внимание, что  автоматически генерируемый UpdateSQL проверяет  только соответствие первичного ключа (where field = :old_field). То есть, обновление записи произойдет независимо от старых или новых значений столбцов. Это поведение отличается от умолчательного поведения компонент BDE TTable и TQuery. У них было свойство UpdateMode, которое отвечало за проверки модификации записи. Это свойство позволяло контролировать возможное "перекрытие" обновлений для случаев, когда пользователь выполняет редактирование записи "долго", а другой пользователь может успеть отредактировать эту же запись и сохранить ее раньше. То есть, первый пользователь на этапе редактирования даже не будет знать, что запись уже изменилась, возможно не один раз, и сумеет "затереть" эти обновления своим:

upWhereAll (по умолчанию) - проверка  на существование записи по  первичному ключу + проверка всех  столбцов на старые значения. например

update table set ... where pkfield = :old_ pkfield and client_name = :old_client_name and info = :old_info ...

То есть, в данном случае запрос поменяет информацию в записи только в том случае, если запись до нас никто не успел изменить. Особенно это важно, если существуют взаимозависимости между значениями столбцов - например, минимальная и  максимальная зарплата, и т.п.

upWhereChanged - проверка записи  на существование по первичному  ключу + плюс проверка на старые  значения только изменяемых столбцов.

update table set ... where pkfield = :old_pkfield and client_name = :old_client

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

upWhereKeyOnly - проверка записи  на существование по первичному  ключу. 

 

Последняя проверка соответствует  генерируемому автоматически для UpdateSQL запросу. Поэтому, при возможных  конфликтах обновлений в многопользовательской  среде необходимо дописывать условия  к where самостоятельно. И, разумеется, также  необходимо при реализации аналога upWhereChanged удалять лишние изменения  столбцов в update table set ... - то есть, оставлять  в перечне set только действительно  измененные столбцы, иначе запрос перепишет  чужие обновления этой записи.

Как вы понимаете, это означает необходимость динамического конструирования  запроса UpdateSQL. Если вы не хотите это  делать и используете ClientDataSet в своих  приложениях, то вполне можно обойтись корректными настройками DataSetProvider (свойства ResolveDataSet и Options).

 

Вместо запросов в InsertSQL/UpdateSQL/DeleteSQL (и вообще их все необязательно  заполнять, можно только часть, например, если удаление не допускается) можно  указывать вызов хранимых процедур. Это позволяет "редактировать" запросы, которые представляют собой объединения нескольких таблиц, агрегаты (группировки) и т.п. случаи, когда нет прямого соответствия между записями в таблицах и записями, возвращаемыми запросом.

 

! в коде приложения  для открытия и закрытия IBDataSet рекомендуется вызывать его методы Open/Close, а не управлять свойством  Active. Во-первых, это почти одно и то же, а во-вторых, Open/Close лучше читаются и не допускают неоднозначностей (как например IBDataSet.Active:=MyVar).

 

Описание методов ExecQuery, Prepare аналогично IBQuery, см. дальше.

Буферизация записей

 

Открытие запроса, возвращающего  набор записей (Active:=True или вызов Open), приводит всего лишь к выполнению запроса, но не к выборке записей. Выборка записей начинается только тогда, когда происходит вызов методов Next, Last или FetchAll (Locate рассмотрен дальше, отдельно). Соответственно, свойство RecordCount показывает только число выбранных в буфер (с сервера) записей. IBCustomDataset и его наследники после Open выбирают только 1 запись в буфер, на чем выборка записей останавливается. Если DataSet подключен к DBGrid, то DBGrid, показывая записи, автоматически вызовет DataSet.Next столько раз, сколько поместилось записей на экран. При дальнейшем продвижении в DBGrid будут считываться остальные записи. По достижении конца выборки (последней записи) сервер сообщает клиентской части что записи кончились, после чего все выбранные записи находятся в буфере DataSet, и любое продвижение по записям вверх или вниз (Next, Prev) приводит только к перемещению указателя внутри буфера DataSet (без обращения к серверу).

 

Если запрос не вернул ни одной записи, то оба свойства - BOF и EOF - будут равны True.

Обновление данных

 

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

 

Если не вдаваться в  подробности (также см. статью), то можно дополнить к предыдущему разделу (буферизация записей), что увидеть новые (committed) данные можно только выполнив запрос снова. Для этого, разумеется, нужно закрыть и открыть IBDataSet (или IBQuery/IBSQL). Переоткрытие (Close/Open) датасета приведет к уничтожению старого буфера записей, перевыполнению запроса, и считыванию записей в буфер. После чего опять до переоткрытия запроса изменения, выполненные другими приложениями (или в других транзакциях) опять будут "не видны".

Перебор записей

 

Для обработки всех записей, возвращаемых запросом, можно использовать цикл:

IBDataSet.Open;

while not IBDataSet.EOF do

  begin

    .. // действия с  текущей записью 

    IBDataSet.Next;  

  end

 

Аналогичный код будет  работать и для IBTable, IBQuery.

Master-Detail

 

Странно, но такой вопрос часто возникает у разработчиков, которые начинают осваивать IBX. Если предполагать, что они перешли  с BDE, то в IBX все делается точно так  же, как в BDE master-detail на компонентах TQuery. Если опыта в подобных вещах нет, то вот пример:

кладем IBDatabase, IBTransaction, соединяем  их

кладем 2 IBDataSet (IBQuery) и 2 TDataSource. Соединяем IBDataSet с IBDataBase, IBTransaction и DataSource

В базе есть 2 таблицы - клиенты  и заказы. Клиенты - master, заказы - detail.

IBDataSet1 + DataSource1 называем MDS и  MasterSrc соответственно. Прописываем  у MDS в SelectSQL запрос 

select * from clients

IBDataSet2 + DataSource2 называем DDS и  DetailSrc соответственно. Прописываем у DDS в SelectSQL запрос

select * from orders where client_id = :cid.

Здесь имя параметра :cid должно совпадать с именем столбца первичного ключа в таблице clients. В данном примере этот столбец и называется CID.

у DDS указываем свойство DataSource = MasterSrc.

Активируем IBDatabase, IBTransaction, затем  сначала MDS, затем DDS (можно еще проверить  на форме, нажав правую кнопку и в  меню CreationOrder, что компоненты создаются  и активируются (открываются) в правильном порядке, и MDS+MasterSrc создаются раньше чем DDS+DetailSrc).

Подсоединяем 2 DBGrid, к MasterSrc и DetailSrc

Запускаем приложение. При перемещение по гриду master показываются соответствующие записи таблицы detail

 

В дополнение к master-detail хочется  отметить еще один вопрос, который  как таковой не относится к IBX. Иногда разработчики, не прочитав внимательно  статью по генераторам, пытаются генерировать идентификатор мастера в триггере, в результате чего не могут ни откуда взять идентификатор мастера  для вставки в таблицу detail. Само-собой, идентификатор надо сначала получить (например, установкой свойства GeneratorField у IBDataSet или IBQuery), использовать для вставки  запись в master-таблицу, а затем в  таблице detail этот идентификатор "возьмется" автоматически. Или он уже и так  будет известен даже при ручной вставке  записи в таблицу detail.

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