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.
Что описать? Как перехватить и отменить события 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
На всякий случай (все равно уже подготовил)
|
|
olegenty |
Отправлено: 18.06.2004, 15:12 |
|
Ветеран
Группа: Модератор
Сообщений: 2412
|
спасибо, дома поразбираюсь
|
|
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, спасибо за помощь
|
|
AVC |
Отправлено: 21.06.2004, 09:35 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
В качестве идеи.
В последнем проекте я все простые справочники свел в одну таблицу по принципу: "Cправочник", "Value_Sting", "Value_Num", "..." пока что результат меня удовлетворяет и плюсы перевешивают минусы.
Обманы компонентА нужны были лишь для того, что бы Grid считал что работает с живым набором данных.
Отредактировано AVC — 21/06/2004, 09:39 |
|