![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как сделать Refresh для одной записи ClientDataSet
OlkaGTS © (2003-08-07 13:49:00)
Уважаемые!
Есть трехуровневое приложение. На клиенте ClientDataset получается joinом из нескольких таблиц. В приложении-сервере у DataSetProvider в BeforeUpdateRecord вызывается хр пр, которая это все сохраняет. Но после всего этого я не вижу поле типа identity на клиенте, а делать Refresh всему dataset не хочется, потому что изменения на сервере должны сохраняться после каждого post. Можно ли каким-то другим способом получить значение этого поля?
Nikolay M. (2003-08-08 11:13:00) [1]
> при твоем способе
Это совсем не мой способ :)
Хоть я сначала и придумал его, а потом уже только прочитал статью на rsdn.
Можно поизвращаться, искуственно ввести дополнительно временный Primary Key, который будет генерироваться случайным образом из очень широкого диапазона... Но красотой такой вариант не блещет :(
Polevi (2003-08-08 10:51:00) [2]
при твоем способе придется писать курсор
если поле AutoInc все делается одним
INSERT INTO .. SELECT FROM
если стоит задача независимости от БД, тогда всю логику нужно реализовать на middleware, а БД использовать только как набор таблиц и индексов, и никаких SP, ф-ий, курсоров и тд, только SQL 92
если такой задачи нет - незачем отказываться от функциональности СУБД и сочинять велосипеды
Polevi (2003-08-08 10:47:00) [3]
2, отношение 1 ко многим
Nikolay M. (2003-08-08 10:34:00) [4]
> Polevi © (07.08.03 20:38)
> например мне нужно выполнить SP на сервере которая сделает
> INSERT нескольких записей - при таком подходе это будет
> не просто сделать, если в таблице есть уникальное поле
А зачем пользоваться этим методом там, где он себя не оправдывает?
> есть таблицашапок документов и их содержимого
> в таблице содержимогокластерный индекс
Таблиц все-таки одна или две?
Polevi (2003-08-08 09:39:00) [5]
>напиши мне XP
сорри, SP конечно
Polevi (2003-08-08 09:38:00) [6]
2Nikolay M. © (07.08.03 23:04)
есть таблица шапок документов и их содержимого
в таблице содержимого кластерный индекс
напиши мне XP которая сделает копию документа
БД MS SQL сервер
corte ™ (2003-08-08 07:50:00) [7]
А букмарками не пользовался ?
Nikolay M. (2003-08-07 23:04:00) [8]
> Насчет получения уникальных значений см http://rsdn.ru/article/db/midas_migration.xml
> в частности,
> http://rsdn.ru/article/db/midas_migration.xml#XSLTSECTION124143120120
Именно это и пытаюсь втолковать, пока не очень получается :(
Polevi (2003-08-07 20:38:00) [9]
2Romkin © (07.08.03 18:57)
например мне нужно выполнить SP на сервере которая сделает INSERT нескольких записей - при таком подходе это будет не просто сделать, если в таблице есть уникальное поле
Romkin (2003-08-07 18:57:00) [10]
Опять счетчики... Так надоело...
>А по классической технологии в том смысле, что все первичные ключи - это поля identity и никак иначе
Мдя, что за классика? Явно форма выше НФБК. Насчет получения уникальных значений см http://rsdn.ru/article/db/midas_migration.xml
в частности,
http://rsdn.ru/article/db/midas_migration.xml#XSLTSECTION124143120120
Все описано, все работает.
Polevi (2003-08-07 18:29:00) [11]procedure TRDM.BeforeUpdateRecord_(Sender: TObject; SourceDS: TDataSet;
DeltaDS: TClientDataSet; UpdateKind: TUpdateKind; var Applied: Boolean);
begin
if UpdateKind=ukInsert then
begin
qry:=TADOQuery.Create(nil);
try
qry.Connection:=SomeAdoConnection;
qry.SQL.Add("EXEC bla-bla-bla);
qry.SQL.Add("SELECT @@IDENTITY");
qry.Open;
DeltaDS.FieldByName("ID").ReadOnly:=false;
( "ID")procedure TRDM.BeforeUpdateRecord_(Sender: TObject; SourceDS: TDataSet;
DeltaDS: TClientDataSet; UpdateKind: TUpdateKind; var Applied: Boolean);
begin
if UpdateKind=ukInsert then
begin
qry:=TADOQuery.Create(nil);
try
qry.Connection:=SomeAdoConnection;
qry.SQL.Add("EXEC bla-bla-bla);
qry.SQL.Add("SELECT @@IDENTITY");
qry.Open;
DeltaDS.FieldByName("ID").ReadOnly:=false;
DeltaDS.FieldByName("ID").NewValue:=qry.Fields[0].Value;
finally
qry.Free
end;
Applied:=true;
end;
end;
Nikolay M. (2003-08-07 17:59:00) [12]
Ну и создай хранимую процедуру, которая эти PRIMARY KEY будет тягать из таблицы. Только блокировку на уровне записи не забыть наложить. И чем это не генерация ID на уровне БД?
Нет, ну если очень хочется, тогда
CDS.Active := False;
CDS.Active := True;...
Пользователи спасибо скажут :)
OlkaGTS (2003-08-07 17:27:00) [13]
CREATE TABLE TT ([ID] int identity(1,1) PRIMARY KEY и т.д.) - этот первичный ключ и имелся ввиду.
А по классической технологии в том смысле, что все первичные ключи - это поля identity и никак иначе и генерироваться значения должны сервером, поскольку с базой работает не одно приложение
Nikolay M. (2003-08-07 17:15:00) [14]
> Отсюда следует, что вытягивание @@Identity ничего не дает,
> поскольку я его потом никуда не могу записать, так как автоинкрементные
> поля Read Only.
SET IDENTITY_INSERT MyTable ON
еще никто не отменял.
> получить ID только что вставленной записи невозможно никак,
> кроме как Refresh всему DataSet?
В таблице есть еще первичные ключи? Скажем, уникальное название или еще что-то... По нему можно вытянуть ID.
> База должна работать по классической технологии.
Диплом???!
OlkaGTS (2003-08-07 16:53:00) [15]
Я не могу изобретать никакие новые методы. База должна работать по классической технологии. Отсюда следует, что вытягивание @@Identity ничего не дает, поскольку я его потом никуда не могу записать, так как автоинкрементные поля Read Only.
Т.е. насколько я понимаю, получить ID только что вставленной записи невозможно никак, кроме как Refresh всему DataSet?
Nikolay M. (2003-08-07 14:53:00) [16]
Как раз проблема именно в этом. Кто тебе сказал, что после INSERT провайдер будет сразу делать SELECT только что вставленной записи? И опции тут не помогут. А если будешь делать одним из методов, как я сказал в
> Nikolay M. © (07.08.03 14:30)
, тогда и проблемы не будет. Для MS SQL можно рискнуть вытянуть @@IDENTITY или как она там зовется, не помню точно - ID последней вставленной записи, но есть вероятность нарваться...
Короче, мой совет - вставлять запись с уже известным на уровне провайдера ID. Вот тогда poAutoRefresh и poPropagateChanges вернут это значение назад на клиент. Но от БД на провайдер значения придут только после Refresh-а.
OlkaGTS (2003-08-07 14:37:00) [17]
Проблема не в этом. Значение поля генерирует сам сервер, но после сохранения я не вижу это значение на клиенте, пока не сделаю Dataset.Refresh. При этом обновятся все записи, а мне нужно только одна конкретная, которую только что вставили.
У провайдера в options есть poAutoRefresh и poPropagateChanges, которые вроде бы должны это делать. Но они этого почему-то не делают
Nikolay M. (2003-08-07 14:30:00) [18]
Тогда можно завести таблицу CREATE TABLE (id_value INTEGER, table_name VARCHAR(255)) и сваять под нее маленькую процедурку, которая по имени таблицы будет возвращать каждый раз автоинкреметное id_value.
Кстати, раз уж у тебя трехзвенка, то можно вообще ID на уровне RemoteDataModule генерировать :) Только не забыть генерацию в критической секции делать - многопоточность все-таки. Ну или любой другой способ синхронизации потоков, какой больше нравится.
OlkaGTS (2003-08-07 14:06:00) [19]
БД MSSQL. Там не генераторов
Nikolay M. (2003-08-07 14:04:00) [20]
БД какая?
В IB делалось так: создавалась хранимая процедура, которая при каждом вызове возвращала автоинкрементное значение генератора (можно и просто табличку для этого завести) и которое потом уже использовалось во всяких
INSERT INTO table (ID, ...) VALUES (:ID, ...)
и тп.
Очень удобно, когда редактируется одна из нескольких связанных таблиц.