-
Доброго времени суток, господа.
И снова тот самый пример из папки DEmos, посвященный RDS-ADO
Добавил на сервер свойство для чтения и записи, соответственно появился метод для записи.
Как правильно осуществлять запись в БД с клиента?
Если поставить навигатор и просто добавлять, к примеру, запись в дбгрид, то на рефреш возникает ошибка "недостаточно сведений из основной таблицы для обновления". Первичный ключ здесь очевидно не причем, потому что на удаление такая же проблема.
Код на клиенте банален: RDSConnection1.Close; ADODataSet1.Close; ADODataSet1.Open;
Код метода обновления на сервере (Метод появляется при добавлении в библиотеку типов свойства на запись/чтение) try AdoConnection1.BeginTrans; Value.UpdateBatch (adAffectAll); AdoConnection1.CommitTrans; except on E:Exception do begin AdoConnection1.RollbackTrans; ShowMessage(E.Message); end; end;
Я конечно в курсе, что многие посоветуют написать на бумажке слово RDS после чего бумажку сжечь и воспользоваться сокетами или чем еще, но отвертеться от РДС никак не могу.
Беда всей темы в том, что найти нормальный гайд трудно, а книжку Елмановой уже не так просто найти)
Спасибо
-
> "недостаточно сведений из основной таблицы для обновления". > Первичный ключ здесь очевидно не причем, потому что на удаление такая же проблема. ??? ошибка явная, и понятная. выводы не понятны. для удаления типа идентификация записи не нужна?
-
Дело в том, что таблица загружается целиком в дбгрид, и в том числе, с полем ID, и при удалении информация об ID имеется.
При добавлении записи поле ID не поддается редактированию в дбгриде оО, может это и логично ибо ID назначается инкрементом.
Очевидно, что я что-то делаю неправильно, как мне лучше организовать обновление? Потому что если просто подключить датасет напрямую через строку подключения на локальной машине, то привязанный к нему дбгрид превосходно все обновляет и никаких ID не просит
-
Согласно примеру, организовал все так:
на сервере есть свойство Property1 с доступностью Read\WRITE и методами
function TLOL.Get_Property1: _Recordset; begin Result := CoRecordSet.Create; Result.CursorLocation := adUseClient; Result.Supports(adUpdateBatch); Result.Open('units', ADOConnection1.ConnectionString, adOpenDynamic, adLockBatchOptimistic, adCmdUnspecified); end;
procedure TLOL.Set_Property1(const Value: _Recordset); begin try AdoConnection1.BeginTrans; Value.UpdateBatch (adAffectAll); AdoConnection1.CommitTrans; except on E:Exception do begin AdoConnection1.RollbackTrans; ShowMessage(E.Message); end; end; end;
На клиенте тупо открывается датасет, привязанный по RDSConnection, в свойстве CommandText которого указано "Property1"
RDSConnection1.Close; ADODataSet1.Close; ADODataSet1.Open;
Данные успешно загружаются, но обновлению не подлежат(
Вот собственно в том и вопрос, как сделать их обновляемыми, смущает adUpdateBatch, просто не знаю пока как организовать правильно
-
> и при удалении информация об ID имеется. этого мало, надо указать что обновление идет по ключу. (почитай статьи на королевстве дельфи про ADO)
+ открываешь почему то ADODataSet1.Open; а запить в Value.UpdateBatch (adAffectAll); ??? плюс откуда то взялся коннект AdoConnection1.BeginTrans;, откуда если RDSConnection1. уж не на сервере ли рулить пытаешься?... а он откуда данные возьмет без передачи с клиента?
-
>этого мало, надо указать что обновление идет по ключу. >> если просто подключить датасет напрямую через строку подключения на локальной машине, то привязанный к нему дбгрид превосходно все обновляет.
Первичный ключ в таблице есть
>+ открываешь почему то ADODataSet1.Open; а запить в Value.UpdateBatch (adAffectAll);
Да, именно это смущает, я просто нашел такой пример, он не совсем подходит, поскольку для другого случая, я просто банально не знаю как это сделать правильно.
>>плюс откуда то взялся коннект AdoConnection1 Ну тут так: Есть клиент и сервер приложений. Сервер приложений подсоединяется через АДО к базе (через строку подключения), а клиент к серверу - через RDS.
В данном случае RDS предоставляет клиенту доступ к свойствам Com-объекта - сервера приложений. Свойство Property1 имеет два метода - на чтение и запись. При обращении к имени свойства на клиенте фактически вызывается метод чтения.
Вот я никак не могу понять, когда вызывается метод на запись, и что должно быть в его реализации на сервере. Пока исходил из того, что при обновлении рекордсета датасета должен вызываться метод записи, вероятно это не так(
Был бы очень благодарен, если бы кто-нибудь привел пример, как должен выглядеть этот метод, и каким образом обратиться к нему в клиенте, в этом, собственно мой вопрос и заключался)
-
> я просто нашел такой пример а подумать? > Сервер приложений подсоединяется через АДО к базе (через строку подключения), а клиент к серверу - через RDS. ВОТ ТУТ, все правильно написано, так и должно быть. а в коде почему то бред.
> Был бы очень благодарен, если бы кто-нибудь привел пример кто его писать будет? нафига оно нам? мне по крайней мере. когда то изучал/искал/писал примеры... после неудач с внедрением бросил это дело.
единственное, что помню/или по логике должно быть, могу посоветовать... так например 2, или даже 3 важных момента 1 UpdateBatch делается с клиента, там где вносятся/меняются данные (там же должна быть настройка adUpdateBatch). 2 на сервере достаточно одного ADOConnection1... 3 блин, выкинь из кода все несущественное для тебя пока ну типа, BeginTrans, CoRecordSet.Create; псевдо обработку ошибок ShowMessage(E.Message); (вот что, серьезно стандартного сообщения мало/оно кривое чтобы в тесте вот эту хрень вставлять?) вместо одной строки кода, важной, у тебя получается 50... а ты еще хочешь разобраться...
и да, начни со стандартного демо, которое сам же приводил. просто добавь кнопку с UpdateBatch(без параметров пока), как можно проще в общем... работает? добавь еще, и т.д.
-
Спасибо за терпение) > на сервере достаточно одного ADOConnection1... так оно одно и есть) >блин, выкинь само собой, это так, осталось просто с первых попыток > и да, начни со стандартного демо в стандартном демо есть только чтение, в том и беда) >CoRecordSet.Create Ну без этого никак. Это собственно и было в демо. Пример с батчем взял отсюда: http://www.delphigroups.info/2/da/224270.htmlэто единственный пример который я нашел. я понимаю что он для другого случая, но данные должен обновлять, попробовать должен был, надеялся что ткнут и скажут - "ненене так нельзя, тут все просто, надо так и так". Разумеется не рассчитывал, что для меня кто-то будет что-то рюхать заново, просто понадеялся что кто-то уже поборол эту проблему и сможет подсказать. В любом случае спасибо, продолжу долбаться, авось повезет. Если решу проблему, напишу как, мало ли кого заставят делать трехзвенку на рдс
-
Пример в ссылке работает, между прочим. Если повесить обновление на отдельную кнопку и обращаться к обновляющему методу на сервере в в ее обработчике - то все хорошо.
Однако ошибка при рефреше навигатора "недостаточно сведений из основной таблицы для обновления" все равно возникает, в то время когда к той же таблице тот же ДатаСет спокойно подключается через строку, и обновляется без проблем. Вопрос изменения "на лету" через свойство сервера остается открытым.
-
> Пример в ссылке работает, между прочим. Если повесить обновление на отдельную кнопку и обращаться к обновляющему методу на сервере в в ее обработчике - то все хорошо. а может он под это и написан? с чего взял что при UpdateBatch должен вызываться (ADO вызывает) именно этот метод? точку останова в нем поставь останавливается?
> "недостаточно сведений из основной таблицы для обновления" читай выше я уже ответил от чего такое.
и кстати, пример в Demo тоже работает между прочим... проверил. одна кнопка с UpdateBatch() в клиент добавляется... и все обновляется, выбирать только RDSServer.DataFactory. если же выбирать самописный сервер, то там нужно исправить adUseClient на adUseServer в Get_Employee и все тоже начинает обновляться. ну или ищи как метод апдейта реально описывается и пиши его самостоятельно. пример из ссылки явно делает неправильно раз не работает в обычном режиме.
-
++ в примере "из ссылки" еще есть глюк похоже (если это реально должен быть метод на стандартный апдейт), т.к. этот апдейт посылает только изменения, т.е. малую часть рекордсета в основном, а в примере эти изменения принимаются как целая таблица.
-
>>должен вызываться (ADO вызывает) именно этот метод Та в том то и дело, что метод обновления Property1 вообще никогда не вызывается, более того, к нему обратиться через RDS.AppServer нельзя даже.
Там в примере - это самостоятельный метод, не привязанный к свойству. Сделал аналогично у себя, и работает, вполне устраивает, конфликты и уровни изоляции можно отрабатывать. На том и остановлюсь, сроки уж поджимают)
Но при этом все равно непонятно, как работать со свойством на запись. В том и беда, что при подключении через АДОконнект все прекрасно обновляется из дб грида прямиком в базу, в вот если через RDS и свойство, то думать и искать( Это надо уже на COM форум)))
>>RDSServer.DataFactory Ну это понятно, это только на локальной машине. А если в самописном сервере исправить на UseServer, то вылетает "Библиотека не зарегистрирована", пробовал. Наверное это можно как-то поправить, впрочем
Вообще, спасибо колоссальное за помощь, Sniknik. Если после выполнения работы удастся найти более изящный и правильный вариант, обязательно напишу сюда, вдруг кто будет париться.
-
> "Библиотека не зарегистрирована" ну так, зарегистрируй. запусти один раз сервер на клиенте.
> найти более изящный и правильный вариант на сокетах, тебе предлагали. все проблемы решаются запуском 1 борландовской службы на сервере.
-
>>>RDSServer.DataFactory > Ну это понятно, это только на локальной машине. ну естественно... если имя компа не указывать. а вообще это полноценный DCOM сервер. правда у него насколько помню есть ограничение, нужно заранее в настройках сервера, разрешения, все используемые с клиента запросы прописать... или что то типа.
-
|