Использование компонентов IBX в Builder 6 С++

IBX, FIBPlus, UIB, ADO, .Net и прочее-прочее-прочее, в общем все, что относится к созданию приложений, работающих с InterBase, Firebird и Yaffil - клиент-серверных, трехзвенных, консольных и т.п.

Модератор: kdv

Шмель
Сообщения: 17
Зарегистрирован: 11 май 2006, 20:48

Использование компонентов IBX в Builder 6 С++

Сообщение Шмель » 11 май 2006, 20:51

Здравствуйте. Прошу направить меня по правильному пути при использовании компонентов IBxxx (InterBase):
1. Интересует возможность редактирования записей в компоненте IBTable. Работает также, как и Table?
2. Может ли компонент IBTable отображать таблицу, если в ней есть поля содержащие "ссылки" на другие таблицы? Т.е. в данном поле хранятся лишь индексы каких-то данных, которые, соответственно, хранятся в другой таблице. Или же необходимо использовать IBQuery и потом обрабатывать самостоятельно, в том числе и редактирование. Как еще варианты?
Спасибо.

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 11 май 2006, 21:33

не надо IBTable. используй IBDataSet. читай
www.ibase.ru/devinfo/ibx.htm

Шмель
Сообщения: 17
Зарегистрирован: 11 май 2006, 20:48

Сообщение Шмель » 18 май 2006, 07:48

kdv писал(а):не надо IBTable. используй IBDataSet. читай
www.ibase.ru/devinfo/ibx.htm
Большое спасибо. Многие возникающие вопросы там освещены.

Есть еще вопрос, как правильно осуществить следующее.
Имеем одну главную таблицу, в которой многие поля являются лишь ссылками (индексами) к другим таблицам. Для добавления данных создается форма, на которой для внесения данных по определенным полям используем компонент ComboBox, который должен выводить список из сопутствующих таблиц (расшифровка индекса).
:?: Как правильно вносить данные в список ComboBox'a - кидаем DataSet по заданной таблице, пробегаемся по каждой строчке в поле расшифровки индекса и заносим в ComboBox.Items? Или есть что-то автоматическое для таких случаев? Замечу, что нам нужно для приложения получить (после выбора) не описание индекса, а сам индекс, для использования его в основной таблице. :?:

Dimitry Sibiryakov
Заслуженный разработчик
Сообщения: 1436
Зарегистрирован: 15 сен 2005, 09:05

Сообщение Dimitry Sibiryakov » 18 май 2006, 07:57

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

smu
Сообщения: 39
Зарегистрирован: 29 окт 2005, 10:12

Сообщение smu » 19 май 2006, 19:21

Шмель писал(а): Как правильно вносить данные в список ComboBox'a - кидаем DataSet по заданной таблице, пробегаемся по каждой строчке в поле расшифровки индекса и заносим в ComboBox.Items? Или есть что-то автоматическое для таких случаев? Замечу, что нам нужно для приложения получить (после выбора) не описание индекса, а сам индекс, для использования его в основной таблице. :?:
Можно и проще. LookupComboBox...

Шмель
Сообщения: 17
Зарегистрирован: 11 май 2006, 20:48

Сообщение Шмель » 25 май 2006, 20:43

Здравствуйте. Споткнулся о стандартную ситуацию, но по неопытности не удается ее перешагнуть. Не хватает какого-то нюанса. Суть вопроса в следующем:
При работе с базой данных (InterBase, Builder C++) использую IBDataSet у которых имеются свойства SelectSQL и InsertSQL. Эти запросы используют параметры (:param), причем наборы параметров в этих SQL запросах различаются. С SelectSQL проблем не возникает - послушно работает, а вот когда пытаюсь присвоить значение для параметров из InsertSQL, вылазит сообщение, что такой параметр не известен. Что-то ещё нужно подкрутить? Где-то нужно указать, что скоро будет использоваться InsertSQL и сделать его "активным"?
Верен ли следующий алгоритм вставки:
1.IBDataSet.InsertSQL = ".. :param .. " - записали запрос
2.IBDataSet.Prepare() - проверили правильность запроса
3.IBDataSet.ParamByName("param") = ...
4.IBDataSet.Open
5.IBDataSet.Insert.
И еще. У IBDataSet есть поле GeneratorField, в котором заданный генератор привязывается к указанному полю по различным событиям, в том числе и по добавлению новых строчек. Эта связка нужна для того, чтобы не заморачиваться при вставке новых записей на задание параметра по указанию значения ключевого поля? Т.е. в InsertSQL не нужно указывать поле к которому привязан генератор?
Спасибо.

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 25 май 2006, 22:22

У InsertSQL нет параметров в обычном понимании, он формируется из полей SelectSQL. То есть, если тебе надо задавать значения полям при Insert, изволь их поселектить, после вызова метода Insert заполнить и сделать Post, т.е. отправить на сервер. Поле из GeneratorField в InsertSQL включать нужно, просто компонент сам его заполнит, обратившись к генератору "за кадром", скрытым запросом.

Dioxin
Сообщения: 26
Зарегистрирован: 03 июн 2005, 08:35

Сообщение Dioxin » 26 май 2006, 20:04

а почему именно датасет?
через ибтабле проще...
едит
меняем
пост

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 27 май 2006, 22:05

Dioxin, если ты не умеешь писать нормальные приложения, то это не значит, что на форуме надо советовать всякую муть.

Dioxin
Сообщения: 26
Зарегистрирован: 03 июн 2005, 08:35

Сообщение Dioxin » 31 май 2006, 09:18

Это не совет!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Это вопрос!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Dimitry Sibiryakov
Заслуженный разработчик
Сообщения: 1436
Зарегистрирован: 15 сен 2005, 09:05

Сообщение Dimitry Sibiryakov » 31 май 2006, 10:51

Проще не значит лучше. TIBTable слишком десктопна по идеологии. Отсюда немерянный траффик, загрузка сервера и как результат - тормоза.

Шмель
Сообщения: 17
Зарегистрирован: 11 май 2006, 20:48

Сообщение Шмель » 08 июн 2006, 07:54

Спасибо за ответы. Во многом (понимаю, что это условно) разобрался, многое уже сделал, однако появились ещё вопросы.
Как работая в Builder'e правильно организовать работу по контролю корректности данных (с точки зрения сервера БД):
1. Есть какие-то компоненты, которые могут получить сведения о том, что попытка записи отклонена как некорректный запрос по такой-то причине. Допустим при внесении новой записи прописываемая ссылка (для связанных таблиц) указывает на несуществующий элемент, или запись с таким же значением по уникальному полю уже существует. Получается, что мы должны получать от сервера БД сообщения об ошибках, возможно с указанием их типа.
2. Воспользоваться имеющимися стандартыми средствами и проверять все самим. Т.е. когда мы хотим добавить новую запись с помощью формы (дополнительного окна), то после выбора пользователя всех параметров и нажатия на "Добавить", программа:
а) открывает новую транзакцию типа snapshot
б) проверяет полностью на корректность вводимых данных для данного фиксированного образа БД
в) вносит новую запись в БД и выполняет Commit
г) проверяет в БД, что конфликта транзакций не произошло путем чтения записанных данных и проверке с исходными данными.
Как правильно? Спасибо.

PS: Если в транзакции выполняется последовательность записей, в конце мы выполняем Commit, а одна из множества операций не может быть выполнена (в частности из-за изменения в БД другой транзакцией). Что в этом случае происходит - полный откат?

Dimitry Sibiryakov
Заслуженный разработчик
Сообщения: 1436
Зарегистрирован: 15 сен 2005, 09:05

Сообщение Dimitry Sibiryakov » 08 июн 2006, 08:26

1) Ошибка, конечно, вернется. Компоненты обычно при этом бросают исключение. Его можно ловить и реагировать.
2) Тоже неплохо, особенно если неверные данные отсекаются принудительно (скажем, выбор из списка вместо прямого ввода). Пункт г), вообще-то, бред.
Операции выполняются не во время COMMIT. Если какая-то операция не прошла, ты получишь ошибку сразу. Но commit после этого подтвердит все "прошедшие" операции. Правда, есть исключения и из этого правила...

CyberMax
Заслуженный разработчик
Сообщения: 638
Зарегистрирован: 31 янв 2006, 09:05

Сообщение CyberMax » 08 июн 2006, 08:38

Проверка делается очень просто:
1. На сервере для столбца указываешь внешний ключ на мастер-таблицу. Это знаешь как делать?
2. При попытке вставить/изменить запись с неверным кодом мастера, приложение схватит исключение. Ты должен его обработать (пример на Delphi):
'try
' DataSet.Post;
'exception
' on E: Exception do
' MessageBox(E.Message, mtError, [mbOk], 0);
'end;

Если хочешь, можешь отлавливать какие-то конкретные исключения (например, EDatabaseException).
Когда произойдет исключение, набор останется в том же состоянии, в котором был (dsInsert или dsEdit).
3. Про свой вариант 2 забудь. Навсегда.
4. Могу ошибаться, но при Commit'е не бывает исключений.
Если запрос не может быть выполнен, он просто не выполняется. Транзакция при этом продолжает работать.

Шмель
Сообщения: 17
Зарегистрирован: 11 май 2006, 20:48

Сообщение Шмель » 08 июн 2006, 09:12

Dimitry Sibiryakov писал(а):1) Ошибка, конечно, вернется. Компоненты обычно при этом бросают исключение. Его можно ловить и реагировать.
Необходимо пользоваться событиями IBDataset - OnPostError, OnEditError, OnDeleteError? Этого достаточно? А как определить конкретную причину ошибки? А для IBTransaction вообще ошибок быть не может? Или вообще нужно пользоваться IBEvents?
Я в этом деле абсолютный новичок и не пойму как обрабатывать исключения.

CyberMax
Заслуженный разработчик
Сообщения: 638
Зарегистрирован: 31 янв 2006, 09:05

Сообщение CyberMax » 08 июн 2006, 09:29

Шмель писал(а):Или вообще нужно пользоваться IBEvents?
IBEvents - для отлова событий, которые ты сам себе посылаешь с сервера соответствующей командой. Пока не трогай этот компонент.
Шмель писал(а):Необходимо пользоваться событиями IBDataset - OnPostError, OnEditError, OnDeleteError?
Это события для централизованной обработки соответствующих исключений. Используй их, это даже будет более правильным, чем я тебе предложил. С их помощью ты можешь повесить все датасеты на один обработчик соответствующего исключения.
Шмель писал(а):А для IBTransaction вообще ошибок быть не может?
Я ошибся. Могут быть. Например, при создании индекса. Сам запрос пройдет без ошибок. А вот при коммите, если таблицы используются, то создание индекса отменяется. Но сама транзакция не закрывается. Ты уже потом сам думаешь, отменять все или постить то что есть.

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 08 июн 2006, 12:47

Cybermax писал(а): Я ошибся. Могут быть. Например, при создании индекса. Сам запрос пройдет без ошибок. А вот при коммите, если таблицы используются, то создание индекса отменяется. Но сама транзакция не закрывается. Ты уже потом сам думаешь, отменять все или постить то что есть.
Не ошибся, а отвечал в контексте DML, выполняющегся на execute, в отличие от DDL, выполняющегося на commit, а на execute только пишущего инфу для выполнения в системные таблицы. Если про это забыть и, например, выполнять DDL и DML на одних и тех же или связанных объектах в одной транзакции, то можно изрядно наломать дров в базе.

Dimitry Sibiryakov
Заслуженный разработчик
Сообщения: 1436
Зарегистрирован: 15 сен 2005, 09:05

Сообщение Dimitry Sibiryakov » 08 июн 2006, 14:17

А, вот, например, конфликт изменений в двух транзакциях когда вылезет? Сразу или только по коммиту?

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 08 июн 2006, 14:37

Dimitry Sibiryakov писал(а):А, вот, например, конфликт изменений в двух транзакциях когда вылезет? Сразу или только по коммиту?
Да ты що, Джолтый? (С) :D DML - в зависимости от wait-nowait, ессно, DDL - не знаю, ибо альтерить одну и ту же таблицу как-то не доводилось в два смычка :lol: Если насчёт object in use с ХП - на коммите. Причём на классике конфликт может выразиться просто в падении одного из процессов :)

Dimitry Sibiryakov
Заслуженный разработчик
Сообщения: 1436
Зарегистрирован: 15 сен 2005, 09:05

Сообщение Dimitry Sibiryakov » 08 июн 2006, 14:48

Блин, а почему же у меня откуда-то засело в голове что при каком-то сочетании трансизоляций ошибка должна вылезти при попытке коммита?.. Где-то я на эти грабли наступал... У меня коммит обламывался, а после этого обламывался и дисконнект (транзакция оставалась активной) - пришлось проверять успешность коммита и при необходимости делать роллбэк. Возможно, при TPC... Нет, не помню.

Ответить