Миshук |
Отправлено: 18.10.2006, 12:35 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 36
|
Приветствую. (ADO+ MS SQL 2000)
опыт разработки приложений для работы с БД маленький. До этого использовал простые — одна большая таблица и справочники. Сейчас есть БД с несколькими связанными таблицами. две из них имеют структуры:
главная таблица (табл1):
1 поле: PacientID — int — автоинкриментное (искуственный ключ)
2 поле ............
..........
подчиненная таблица(табл2):
1 поле: ID — int — автоинкриментное(искуственный ключ)
2 поле: PacientID — int -
3 поле: Factors
обе таблицы связаны по полю PacientID. Т.е одной записи в таблице 1 одновременно может соответствовать несколько записей таблицы табл2. В свойствах связи стоит каскадное удаление записей из подчиненной таблицы.
так вот, есть форма с контролами. где-то посреди формы я должен внести данные(несколько записей),которыми заполняется подчиненная таблица, а потом дальше продолжать заполнять контролы, которые связаны с главной таблицей. Проблема состоит в том, что я не могу вставлять записи в подчиненную таблицу, пока не сделаю Post главной(все из- за автоинкрементного поля). а именно такой подход мне и нужен т.е. сначала заполняю часть контролов связ-ых с глав.табл. потом вставляю записи в подчинен.табл. а потом продолжаю заполнять контролы связ-ые с гл.табл. В итоге получается одна запись в главной таблице и несколько записей соответсвующих ей в подчиненной таблице. (что-то растянул, короче 1:n)
Поскажите пожалуйста чем разрулить это. Может явными транзакциями, может какими-нибудь временными таблицами? сначала вставлять записи котроые должны содержаться в подчиненной таблице во временную, а потом после поста главной таблицы сливать их из временной в подчиненную. А может какие компаненты есть сторонние?
Вроде в EhLib есть то что мне надо, но ей пока совсем не пользовался. попробовал бы, но обстоят-ва сложились так, что делаю проект на Делфе7 а EhLib не хочет туда вставать — пакеты даже не компилятся. поэтому может есть варианты без EhLib? Спасибо!
|
|
olegenty |
Отправлено: 18.10.2006, 12:43 |
|
Ветеран
Группа: Модератор
Сообщений: 2412
|
попробуй поигаться с TClientDataSet + CachedUpdates=true;
на sql.ru есть участник — pkarklin, он реализовал то, что тебе требуется, именно таким способом. можешь с ним списаться.
|
|
AVC |
Отправлено: 18.10.2006, 14:28 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
Еше вариант — создаем главную запись с минимально необходимым заполнением полей (как минимум ID). Потом вставляем подчиненные. Потом заполняем остальные поля основной.
Все это дело еще можно обернуть в одну транзакцию.
Или как сказал olegenty — все необходимые записи формируем на клиенте а потом, при сохранении на сервере, достраиваем все записи до требуемого состояния (та же транзакция, но на клиенте:) ). |
|
olegenty |
Отправлено: 18.10.2006, 14:32 |
|
Ветеран
Группа: Модератор
Сообщений: 2412
|
да, как говорит AVC, pkarklin сделал это в управляемой с клиента транзакции.
есть ещё вариант: пихаем новьё в XML, XML отдаём хранимой процедуре, она его разбирает и делает всё, что требуется. MSSQL обладает встроенными средствами разбора XML.
|
|
Миshук |
Отправлено: 30.10.2006, 11:47 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 36
|
Привет!
QUOTE | есть ещё вариант: пихаем новьё в XML, XML отдаём хранимой процедуре, она его разбирает и делает всё, что требуется. MSSQL обладает встроенными средствами разбора XML. |
до этого кажеться вообще еще не дорос.
А вот на счет
QUOTE | Еше вариант — создаем главную запись с минимально необходимым заполнением полей (как минимум ID). Потом вставляем подчиненные. Потом заполняем остальные поля основной. |
Что-то не получается.может я чего не допонимаю. а конкретенее — в XMLке главной таблицы(да и подчиненной) при сохранении записи QUOTE | с минимально необходимым заполнением полей (как минимум ID) | не формируется автоинкрементное поле. Оно появляется только в базе после посылки данных в базу.ну это вроде и как естественно — так думаю СУБД должна формировать автоинкрементное значение. ну а зачем мне тогда формировать записи на клиенте без автоинкрементного значения?
правильно ли я делаю?
к примеру:
CODE |
/// создаю XML файл ....
ClientDataSet->Open();
ClientDataSet->Insert();
.......заполняю какие-то минимально необходимые поля
ClientDataSet->Post();
ну и потом
ClientDataSet->ApplyUpdate(-1);
.........
|
ну и сохранение и передача изменений в базу заворачиваю в транзакцию на клиенте.
Короче, наругайте меня если что-то не так!
Отредактировано Миshук — 30.10.2006, 12:50
|
|
olegenty |
Отправлено: 30.10.2006, 12:10 |
|
Ветеран
Группа: Модератор
Сообщений: 2412
|
и тем не менее XML — это просто.
всего-то
sp_xml_preparedocument
sp_xml_removedocument
OPENXML
|
|
Миshук |
Отправлено: 30.10.2006, 17:05 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 36
|
Привет!
QUOTE | и тем не менее XML — это просто. | Хорошо,покавыряюсь!
Но тем не менее, а как вы осуществляете сохранение записей в master-detail таблицах в многопользовательских приложениях? Спасибо!
P.S. А может таблицы спроектированы неправильно? Да вроде нет!
|
|
AVC |
Отправлено: 31.10.2006, 10:00 |
|
Ветеран
Группа: Модератор
Сообщений: 1583
|
QUOTE (Миshук @ 30.10.2006, 17:05) | как вы осуществляете сохранение записей в master-detail таблицах в многопользовательских приложениях? |
Зависит от СУБД, но основная проблема состоит в получении PK основной записи до создания подчиненных. Для этого можно применить вызов генератора если автоинкремент построен на генераторе или фразу returning команды insert если позволяет синтаксис или, если есть такое — значение глобальной переменной @@identity или, в конце концов, имитатор генератора на SP.
Все вставки обернуты в транзакцию. |
|
olegenty |
Отправлено: 31.10.2006, 10:27 |
|
Ветеран
Группа: Модератор
Сообщений: 2412
|
у меня такое бывает только по окончании работы визардов. на сервер уходит XML. сервер его разбирает и раскладывает по временным таблицам. дальше всё стандартно.
|
|
Миshук |
Отправлено: 03.11.2006, 09:48 |
|
Дежурный стрелочник
Группа: Участник
Сообщений: 36
|
Привет!
Вообщем, я сам не понял зачем я прицепился к XML и создавал локальный файл на машине(портфельный набор), когда можно просто загрузить данные в ClientDataSet поработать с ними (в памяти) и отправить обратно в базу.
Короче,если кому интересно, при сохранении записи из мастер-детайл таблицы сначала как вы и говорили постю запись гл.таблицы (для нее клинтский набор не делал),потом значение ее автоинкрементного поля закидываю в детайл таблицу и ApplyUpdates'ом их в базу. Ну и все энтно акуратно заворачивается в транзакцию. После закрываю КлиентДатаСет, инсертю Основные наборы данных(главный и подчиненный),связанные между собой, и опять открываю КлиентДатаСет для подчиненного набора... и т.д. это что касается процедуры записи данных в базу данных. Всем спасибо!!!
|
|
olegenty |
Отправлено: 03.11.2006, 10:15 |
|
Ветеран
Группа: Модератор
Сообщений: 2412
|
XML я никуда на диск не кладу, это строка, на выходе с визарда генерируется. Что-то типа:
CODE |
<root>
<record FakeOperationID="1" Name="Сборочная операция">
<subrecord UnitIID="123123" Num="12.3"></subrecord>
...
</record>
...
</root>
|
а MSSQL потом разбирает это и кладёт в таблицы.
|
|