C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Lookup поля в Runtime.
olegenty
Отправлено: 18.06.2004, 06:56


Ветеран

Группа: Модератор
Сообщений: 2412



Есть ли способ создавать Lookup поля в Runtime?
TFields не позволяет...
AVC
Отправлено: 18.06.2004, 09:10


Ветеран

Группа: Модератор
Сообщений: 1583



CODE

void __fastcall TForma1::BitBtn1Click(TObject *Sender)
{
TField *fld = Client_Name;
TDataSet *ds = fld->DataSet;
bool needactivate = ds->Active;

if (needactivate) ds->Active = false;

fld->FieldKind = fkLookup;
fld->KeyFields = "ClientID";
fld->LookupDataSet = QCli; // здесь можно поменять текст запроса
fld->LookupKeyFields = "ClientID";
fld->LookupResultField = "Client_FName"; // было BirthDay

if (needactivate) ds->Active = true;
}


И все работает.
На SQL'евских базах данных я забыл что такое LookUp. Более выгодно заставить это делать сервер при помощи связей.

Отредактировано AVC — 18/06/2004, 09:13
olegenty
Отправлено: 18.06.2004, 09:43


Ветеран

Группа: Модератор
Сообщений: 2412



нихрена не понял:
QUOTE

   TField   *fld = Client_Name;


я ещё поразбираюсь.
olegenty
Отправлено: 18.06.2004, 09:54


Ветеран

Группа: Модератор
Сообщений: 2412



мне это надо для создания универсального средства редактирования простых справочников.

в самой БД храню перечень запросов и описание полей.
а создаётся всё в Runtime — заголовки полей, ширина и пр...

всё нормально работает без Lookup, а вот с ним — не позволяет создавать, сволочь, и всё тут. сообщения об ошибке не помню, это было вчера и я был злой.
AVC
Отправлено: 18.06.2004, 10:42


Ветеран

Группа: Модератор
Сообщений: 1583



TField *fld = Client_Name это имя предопределенного поля.Сделано для простоты теста. Обычно я использую DataSet->FindField("Field_Name").

Для построения универсальных редакторов я договариваюсь (сам с собой) о способе именования полей. FK поля во всех таблицах иеют имя PK родительской таблицы. Имя PK формируется как TableNameID и имеет тип, приводимый к Number. Даже если такой первичный ключ мне не нужен, я все равно делаю в таблице AlterPK с этими свойствами. Пояснительная информация к PK находится в поле TableName_Name. Использование этих соглашений позволяет мне автоматически генерить текст запроса для простых справочников или связок. Т.е указав имя "базовой" таблицы я по именам полей могу судить что ей еще надо.
olegenty
Отправлено: 18.06.2004, 10:45


Ветеран

Группа: Модератор
Сообщений: 2412



Lookup поле ещё не существует в наборе, и FieldByName(...) его не даст, его как раз надо создать...
olegenty
Отправлено: 18.06.2004, 10:47


Ветеран

Группа: Модератор
Сообщений: 2412



а редактировать в гриде слабо? у меня ещё задача редактирования в гриде стоит, вот беда в чём. иначе я бы не парился Вооооообще.
AVC
Отправлено: 18.06.2004, 11:15


Ветеран

Группа: Модератор
Сообщений: 1583



Все, что я описал, делается для редактирования ИМЕННО в гриде. По описанию типов полей я подбираю им редакторы. Если поле определяется как LookUp (соответствует моим соглашениям об именовании и есть соответствующая таблица) то колонка с полем ??ID visible = false, а на поле с ??_Name вешается редактор типа выбор одной строки. Сам редактор выбора унифицирован и снабжен механизмом добавления новых записей.
olegenty
Отправлено: 18.06.2004, 11:49


Ветеран

Группа: Модератор
Сообщений: 2412



давай по порядку.
вариант 1
1. создаётся запрос. если он с JOIN, то набор данных необновляемый, следовательно без JOIN, к редактируемой таблице
2. открываем запрос. смотрим — есть ссылка на связанную таблицу по некоторому полю. оч. хорошо. но как его отобразить в гриде? набор данных уже открыт, создать поле и присовокупить его к набору — нереально, ругается компонент набора данных

вариант 2
1. то же самое
2. до открытия набора проверить наличие полей, требующих связи, и добавить их в набор. тогда при открытии набора возникает другая ошибка: не находит FK, непонятно почему. но суть не меняется — не работает...

вариант 3
1. запрос с JOIN, всё отображается, отлично! но набор данных нередактируемый... чё делать?
AVC
Отправлено: 18.06.2004, 11:58


Ветеран

Группа: Модератор
Сообщений: 1583



QUOTE

вариант 3
1. запрос с JOIN, всё отображается, отлично! но набор данных нередактируемый... чё делать?

У нас уже был диалог на эту тему. Я давным давно решил для себя эту проблему перехватывая события у DataSet и формируя Insert или Update запросы, обрабатываемые через другой DS. Следовательно осталась одна проблема как заставить грид считать что DS изменяемый. Я знаю решения для TQury и TOracleDataSet, я НЕ знаю решения для ADO — не работаю с ним, но могу поискать. Найду — сообщу.
olegenty
Отправлено: 18.06.2004, 12:07


Ветеран

Группа: Модератор
Сообщений: 2412



опиши вкратце, думаю сам разбирусь, я такую задачу себе не ставил. но пока и решения не вижу (на вскидку).
в общем — ты опиши, а я подумаю, какого наследника создать... (ну, если не добью свой вариант...)
AVC
Отправлено: 18.06.2004, 13:28


Ветеран

Группа: Модератор
Сообщений: 1583



По поводу ADO стал эксперементировать — получилось следующее.
Бросаю компонент TADQuery настраиваю связь на Oracle (просто потому, что он под рукой). Заполняю SQL
Select a.*, b.* From avc.Aaa a, hhc.ZUser Where a.ZUserID = b.ZUserID
Таблица AAA в моей области это копия таблицы ZUser (для усложнения эксперимента все поля дублированы).
Связываю стандартный DBGrid с Query.
Запускаю.
Свододно в гриде перхожу в редактор. Изменяю значения полей. Результат сохраняется в двух таблицах одновременно.
Во как! Может это потому, что Oracle? Потом попробую на FB.

QUOTE
в общем — ты опиши

Что описать? Как перехватить и отменить события DataSet'а или как обмануть Grid?

Отредактировано AVC — 18/06/2004, 13:31
olegenty
Отправлено: 18.06.2004, 13:45


Ветеран

Группа: Модератор
Сообщений: 2412



как грид обмануть.
события вроде без проблем перехватыватываются и так.
AVC
Отправлено: 18.06.2004, 14:30


Ветеран

Группа: Модератор
Сообщений: 1583



Грид определяет возможность Edit'а по DataSet -> обманывать надо через DS

TQuery (и так знаешь)
RequestLive = true, OnUpdateRecord !NULL, UpdateObject !NULL точно не помню но кажется из двух последних хватает любого одного.

TADOQuery
мне обманывать не пришлось (см. предыдущее сообщение)

TOracleDataSet
Наличие среди полей поля RowID или OnApplayRecord !NULL

На всякий случай (все равно уже подготовил)

User Attached Image Скачать файл
DSGrid.txt


olegenty
Отправлено: 18.06.2004, 15:12


Ветеран

Группа: Модератор
Сообщений: 2412



спасибо, дома поразбираюсь smile.gif
AVC
Отправлено: 18.06.2004, 15:32


Ветеран

Группа: Модератор
Сообщений: 1583



Незачто.
По ADO
Зацепил ADO'м FireBird выборка из двух таблиц. Все по прежнему: сетка не препятствует редактору. Провайдер (первый подошедший) MSDASQL.1
olegenty
Отправлено: 18.06.2004, 15:42


Ветеран

Группа: Модератор
Сообщений: 2412



я с MS SQL работаю в данном случае.
AVC
Отправлено: 18.06.2004, 16:18


Ветеран

Группа: Модератор
Сообщений: 1583



MS SQL у меня просто нет.
olegenty
Отправлено: 21.06.2004, 09:21


Ветеран

Группа: Модератор
Сообщений: 2412



в общем добил я вопрос всё же по-своему, создаю именно Persistent Lookup поля в Run-time, и всё это работает.

спешил и нервничал, поэтому Access Violation временами возникает, но это уже вопрос отладки в течении ближайшего свободного часа.

в результате, получил я следующее:

1. Написал компонент — коллекцию, хранящую инфу о
1.1. Наборе данных, суть — имя/запрос
1.2. Коллекции полей НД

2. Соглашениями и я пользуюсь, но не в этом случае. А в этом случае у меня в БД есть несколько сервисных таблиц, где и хранится информация о НД справочников и их полях.

3. Гружу в свои коллекции всю эту инфу из БД, или в Design-time заполняю руками — не суть важно, хотя в данном случае — гружу из БД

4. Заполняю комбу списком справочников

5. Выбираю справочник, создаю датасеты, отображаю в гриде.

4. Наслаждаюсь.

Да, и никаких обманов компонентов и т.д., просто внимательней инфу надо было читать. Всем интересующимся рекомендую почитать о конструкторах Persistent полей, создаваемых обычно в Design-time и о том, КАК их правильно создавать в Run-time.

Засим, AVC, спасибо за помощь smile.gif
AVC
Отправлено: 21.06.2004, 09:35


Ветеран

Группа: Модератор
Сообщений: 1583



В качестве идеи.
В последнем проекте я все простые справочники свел в одну таблицу по принципу: "Cправочник", "Value_Sting", "Value_Num", "..." пока что результат меня удовлетворяет и плюсы перевешивают минусы.
Обманы компонентА нужны были лишь для того, что бы Grid считал что работает с живым набором данных.

Отредактировано AVC — 21/06/2004, 09:39

Вернуться в Работа с базами данных в C++Builder