Страница 1 из 2
Использование компонентов IBX в Builder 6 С++
Добавлено: 11 май 2006, 20:51
Шмель
Здравствуйте. Прошу направить меня по правильному пути при использовании компонентов IBxxx (InterBase):
1. Интересует возможность редактирования записей в компоненте IBTable. Работает также, как и Table?
2. Может ли компонент IBTable отображать таблицу, если в ней есть поля содержащие "ссылки" на другие таблицы? Т.е. в данном поле хранятся лишь индексы каких-то данных, которые, соответственно, хранятся в другой таблице. Или же необходимо использовать IBQuery и потом обрабатывать самостоятельно, в том числе и редактирование. Как еще варианты?
Спасибо.
Добавлено: 11 май 2006, 21:33
kdv
не надо IBTable. используй IBDataSet. читай
www.ibase.ru/devinfo/ibx.htm
Добавлено: 18 май 2006, 07:48
Шмель
Большое спасибо. Многие возникающие вопросы там освещены.
Есть еще вопрос, как правильно осуществить следующее.
Имеем одну главную таблицу, в которой многие поля являются лишь ссылками (индексами) к другим таблицам. Для добавления данных создается форма, на которой для внесения данных по определенным полям используем компонент ComboBox, который должен выводить список из сопутствующих таблиц (расшифровка индекса).

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

Добавлено: 18 май 2006, 07:57
Dimitry Sibiryakov
Ответ на этот вопрос сильно зависит от размера "сопутствующих таблиц". Для малого размера (пара десятков записей) - нормально. Для большого
лично я бы сделал не полный список в ComboBox а скорее AutoComplete после того как пользователь наберет достаточное количество символов.
С другой стороны можно ведь справочник вытащить один раз в начале работы и закэшировать на клиенте...
Добавлено: 19 май 2006, 19:21
smu
Шмель писал(а): Как правильно вносить данные в список ComboBox'a - кидаем DataSet по заданной таблице, пробегаемся по каждой строчке в поле расшифровки индекса и заносим в ComboBox.Items? Или есть что-то автоматическое для таких случаев? Замечу, что нам нужно для приложения получить (после выбора) не описание индекса, а сам индекс, для использования его в основной таблице.

Можно и проще. LookupComboBox...
Добавлено: 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 не нужно указывать поле к которому привязан генератор?
Спасибо.
Добавлено: 25 май 2006, 22:22
Merlin
У InsertSQL нет параметров в обычном понимании, он формируется из полей SelectSQL. То есть, если тебе надо задавать значения полям при Insert, изволь их поселектить, после вызова метода Insert заполнить и сделать Post, т.е. отправить на сервер. Поле из GeneratorField в InsertSQL включать нужно, просто компонент сам его заполнит, обратившись к генератору "за кадром", скрытым запросом.
Добавлено: 26 май 2006, 20:04
Dioxin
а почему именно датасет?
через ибтабле проще...
едит
меняем
пост
Добавлено: 27 май 2006, 22:05
kdv
Dioxin, если ты не умеешь писать нормальные приложения, то это не значит, что на форуме надо советовать всякую муть.
Добавлено: 31 май 2006, 09:18
Dioxin
Это не совет!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Это вопрос!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Добавлено: 31 май 2006, 10:51
Dimitry Sibiryakov
Проще не значит лучше. TIBTable слишком десктопна по идеологии. Отсюда немерянный траффик, загрузка сервера и как результат - тормоза.
Добавлено: 08 июн 2006, 07:54
Шмель
Спасибо за ответы. Во многом (понимаю, что это условно) разобрался, многое уже сделал, однако появились ещё вопросы.
Как работая в Builder'e правильно организовать работу по контролю корректности данных (с точки зрения сервера БД):
1. Есть какие-то компоненты, которые могут получить сведения о том, что попытка записи отклонена как некорректный запрос по такой-то причине. Допустим при внесении новой записи прописываемая ссылка (для связанных таблиц) указывает на несуществующий элемент, или запись с таким же значением по уникальному полю уже существует. Получается, что мы должны получать от сервера БД сообщения об ошибках, возможно с указанием их типа.
2. Воспользоваться имеющимися стандартыми средствами и проверять все самим. Т.е. когда мы хотим добавить новую запись с помощью формы (дополнительного окна), то после выбора пользователя всех параметров и нажатия на "Добавить", программа:
а) открывает новую транзакцию типа snapshot
б) проверяет полностью на корректность вводимых данных для данного фиксированного образа БД
в) вносит новую запись в БД и выполняет Commit
г) проверяет в БД, что конфликта транзакций не произошло путем чтения записанных данных и проверке с исходными данными.
Как правильно? Спасибо.
PS: Если в транзакции выполняется последовательность записей, в конце мы выполняем Commit, а одна из множества операций не может быть выполнена (в частности из-за изменения в БД другой транзакцией). Что в этом случае происходит - полный откат?
Добавлено: 08 июн 2006, 08:26
Dimitry Sibiryakov
1) Ошибка, конечно, вернется. Компоненты обычно при этом бросают исключение. Его можно ловить и реагировать.
2) Тоже неплохо, особенно если неверные данные отсекаются принудительно (скажем, выбор из списка вместо прямого ввода). Пункт г), вообще-то, бред.
Операции выполняются не во время COMMIT. Если какая-то операция не прошла, ты получишь ошибку сразу. Но commit после этого подтвердит все "прошедшие" операции. Правда, есть исключения и из этого правила...
Добавлено: 08 июн 2006, 08:38
CyberMax
Проверка делается очень просто:
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'е не бывает исключений.
Если запрос не может быть выполнен, он просто не выполняется. Транзакция при этом продолжает работать.
Добавлено: 08 июн 2006, 09:12
Шмель
Dimitry Sibiryakov писал(а):1) Ошибка, конечно, вернется. Компоненты обычно при этом бросают исключение. Его можно ловить и реагировать.
Необходимо пользоваться событиями IBDataset - OnPostError, OnEditError, OnDeleteError? Этого достаточно? А как определить конкретную причину ошибки? А для IBTransaction вообще ошибок быть не может? Или вообще нужно пользоваться IBEvents?
Я в этом деле абсолютный новичок и не пойму как обрабатывать исключения.
Добавлено: 08 июн 2006, 09:29
CyberMax
Шмель писал(а):Или вообще нужно пользоваться IBEvents?
IBEvents - для отлова событий, которые ты сам себе посылаешь с сервера соответствующей командой. Пока не трогай этот компонент.
Шмель писал(а):Необходимо пользоваться событиями IBDataset - OnPostError, OnEditError, OnDeleteError?
Это события для централизованной обработки соответствующих исключений. Используй их, это даже будет более правильным, чем я тебе предложил. С их помощью ты можешь повесить все датасеты на один обработчик соответствующего исключения.
Шмель писал(а):А для IBTransaction вообще ошибок быть не может?
Я ошибся. Могут быть. Например, при создании индекса. Сам запрос пройдет без ошибок. А вот при коммите, если таблицы используются, то создание индекса отменяется. Но сама транзакция не закрывается. Ты уже потом сам думаешь, отменять все или постить то что есть.
Добавлено: 08 июн 2006, 12:47
Merlin
Cybermax писал(а):
Я ошибся. Могут быть. Например, при создании индекса. Сам запрос пройдет без ошибок. А вот при коммите, если таблицы используются, то создание индекса отменяется. Но сама транзакция не закрывается. Ты уже потом сам думаешь, отменять все или постить то что есть.
Не ошибся, а отвечал в контексте DML, выполняющегся на execute, в отличие от DDL, выполняющегося на commit, а на execute только пишущего инфу для выполнения в системные таблицы. Если про это забыть и, например, выполнять DDL и DML на одних и тех же или связанных объектах в одной транзакции, то можно изрядно наломать дров в базе.
Добавлено: 08 июн 2006, 14:17
Dimitry Sibiryakov
А, вот, например, конфликт изменений в двух транзакциях когда вылезет? Сразу или только по коммиту?
Добавлено: 08 июн 2006, 14:37
Merlin
Dimitry Sibiryakov писал(а):А, вот, например, конфликт изменений в двух транзакциях когда вылезет? Сразу или только по коммиту?
Да ты що, Джолтый? (С)

DML - в зависимости от wait-nowait, ессно, DDL - не знаю, ибо альтерить одну и ту же таблицу как-то не доводилось в два смычка

Если насчёт object in use с ХП - на коммите. Причём на классике конфликт может выразиться просто в падении одного из процессов

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