Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2009.05.17;
Скачать: [xml.tar.bz2];

Вниз

TClientDataSet + ADO + MSSQL   Найти похожие ветки 

 
kaif ©   (2008-09-10 00:50) [0]

2 MsGuns

г) в особо критичных ситуациях "гридного" редактирования не ленись использовать TClientDataSet со всеми его вкусностями (в т.ч. "тонкой" технологией управления кэшированием-отсылкой изменений) - ADO в сеточной режиме ведет себя иногда весьма капризно (особенно в конкурентных соединениях)

Я вот пытаюсь это сделать. С ClientDataSet раньше не работал.

Положил на одну форму:

 ADODataSet1, DataSetProvider1 и ClientDataSet1.

Привязал их:

 ClientDataSet1.ProviderName :=  DataSetProvider1;
 DataSetProvider1.DataSet :=  ADODataSet1;

В ClientDataSet1 добавил persistent-поля в дизайнере с нужными именами и типами.

В ADODataSet1.CommandText вписал текст запроса детальной таблицы. Причем у меня там лежит JOIN двух таблиц (позиций заказов и справочника товаров)

Активизировал запрос.
Активизировал ClientDataSet1.

В верхней сетке (та, что связана с ADODataSet1) данные редактируются и тут же посылаются на сервер. Я вижу в Studio Express, как изменения проявляются в базе. Этот ADO+MSSQL провайдеры настолько умны, что он умудряются не только редактировать позиции заказа (количества), но и изменять наименование товара каким-то фантастическим образом в справочнике товаров.

То есть, похоже, на лету разбираются с тем, какие поля из каких таблиц объединения JOIN я изменяю. Хотя в общем-то мне все это нафиг не нужно. Я хочу (пока это желание присутствует) ручками управлять ситуацией так, чтобы самому в нужный момент сформировать все нужные запросы.

Пойдем далее.

Итак, вижу в нижней сетке , подключенной к ClientDataSet1, набор данных.

При редактировании в этой сетке вижу, что исходный набор в верхней сетке не изменяется, ничего на сервер не посылается. Я безумно рад этому обстоятельству. Значит, я на верном пути.

Теперь я пытаюсь вызвать метод

 ClientDataSet1.ApplyUpdates(0);

У меня возникли некоторые трудности.
Возникает ошибка Invalid column name GOOD_NAME. Это как раз и есть поле справочника.

Все ли я в принципе делаю правильно?
Можно ли перехватить событие обновления датасета?
У меня не получилось (я пытался использовать OnWillChangeRecord и даже OnWillChangeField, но до этих событий, похоже, дело не доходит)


 
kaif ©   (2008-09-10 01:15) [1]

Похоже, моя задача проще решается без ClientDataSet.
Методом ADODataSet1.UpdateBatch().
Хотя соображения выслушать всегда полезно.


 
Johnmen ©   (2008-09-10 09:06) [2]


> kaif ©

Тебе не нужет CDS, достаточно ADODataSet, как имеющего схожий функционал относительно локального кеширования.


 
MsGuns ©   (2008-09-10 09:14) [3]

Не представляя себе сути решаемой задачи, невозможно высказать какие-то соображения.

По поводу "умности" ADO. Есть куча статей в инете, где обсуждается именно эта особенность оболочки - "умение" разобраться в какой таблице что менять и глючность этого "умения".
Эта путаница не в последнюю очередь вынудила меня отказаться от прямого гридного редактирования датасета. Хотя, вполне допускаю, что при достаточнной настырности можно заставить АДО работать корректно во всех случаях, я же предпочитаю обходиться другими, более прозрачными технологиями.

ЗЫ. ИМХО, ветка оформлена не по правилам и может быть удалена,


 
kaif ©   (2008-09-10 09:25) [4]

Я выбросил CDS. Оставил только ADODataSet. Но так и не смог избавиться от редактирования сразу всех таблиц, которое он мне устроил. :(

Пришлось реализовывать обновление в обход, в прямом смысле слова.
Пожалуй ветку действительно можно удалить.


 
Johnmen ©   (2008-09-10 09:29) [5]


> kaif ©   (10.09.08 09:25) [4]

Там где-то в параметрах можно указать, какая таблица должна апдейтиться.
Я не помню... sniknik подскажет.


 
sniknik ©   (2008-09-10 10:37) [6]

> Там где-то в параметрах можно указать, какая таблица должна апдейтиться.
Properties["Unique Table"].Value

и вообще
http://www.delphikingdom.com/asp/itemq.asp?Mode=1&ItemID=128


 
kaif ©   (2008-09-10 11:00) [7]

2 sniknik ©   (10.09.08 10:37) [6]

Спасибо. Properties["Unique Table"].Value сработал.

Но вот не могу задействовать

Update Criteria

Не знаю, что присвоить этому свойству. Мне нужно апдейтить только по первичному ключу. В статье говорится об adCriteriaKey, но такой константы в ADO нет.


 
kaif ©   (2008-09-10 11:15) [8]

Нет, показалось. К сожалению продолжает добавлять в таблицу справочника при инсерте. :(
Зато константу adCriteriaKey нашел.


 
Правильный$Вася   (2008-09-10 11:55) [9]


> Теперь я пытаюсь вызвать метод  ClientDataSet1.ApplyUpdates(0);

в тяжелых случаях можно использовать Provider.BeforeUpdateRecord


 
MsGuns ©   (2008-09-10 15:30) [10]

Насколько я понял, ты не совсем по назначению используешь CDS
ИМХО, есть 2 основных его назначения:

1) "Отложенные" изменения
Датасет использует "прямое" подключение через провайдер, однако позволяет работать даже при потере соединения, сохраняя данные в кэше или даже на лок.диске. При возобновлении соединения делается попытка отправить изменения на сервер и перейти в "онлайн"

2) "Автономная" работа
Датасет динамически создается по "образу и подобию" исходного. Туда "ручками" заливаются данные из исходного, исходный закрывается (в т.ч. включая само соединение). Вся работа ведется в CDS с периодическими (по кнопке или соотв.событиям) сохранениями на лок.диске. По кнопке данные датасета последовательно одиночными параметрическими запросами update-delete-insert) переносятся на сервер. Все выполняется в единой транзакции, запускаемой "ручками" через соединение (ADOConnection.BeginTrans), разумеется с проверками результата записи. Если Ок, цикл продолжается и по его завершении транзакция подтверждается, датасет переоткрывается "напрямую" и работа возобновляется как бы с начала. Если возникла ошибка записи-удаления, транзакция откатывается, причина отображется на экране, ошибочная запись становится текущей в датасете.

Этот способ, возможно, выглядит не совсем "красиво", но работает превосходно именно в конкурентных ситуациях, когда несколько пользователей обращаются к одному и тому же сложному объекту, хранящемуся в БД, и объект должен "выделяться" лишь одному из них.


 
MsGuns ©   (2008-09-10 15:35) [11]

В "автономном" режиме запросто реализуется сеточная правка в эксельной манере - при этом не загружается сервер, нет лишних проверок на целостность, исключена вероятность взаимовлияния пользователей друг на друга при модификациях одних и тех же объектов БД и скорость работы не зависит ни от каких факторов, кроме, конечно, производительности ПК клиента.


 
MsGuns ©   (2008-09-10 15:42) [12]

Еще в пользу CDS:

Он абсолютно не зависит от источника в плане сортировок, фильтров и т.д. В нем есть даже агрегаты, позволяющие делать объединения и итоги "как в экселе" (ну или почти как). Кроме того, полностью управляем в плане что и когда отправлять на сервер. Каждая запись у него имеет статус, который можно анализировать ДО отправки данных провайдеру.
Единственный минус его (впрочем, вполне оборимый через добавление в uses Midas.pas или вроде того) - это неоходимость таскания Midas.dll, с которой могут быть проблемы (например, после установки на клиентский ПК какой-нибудь ранней версии Делфы)


 
kaif ©   (2008-09-10 18:35) [13]

2 MsGuns ©

Сергей, спасибо за столь подробное разъяснение. Я обязательно тщательно изучу работу с CDS в любом случае, чтобы осознанно выбирать наилучший вариант в любой ситуации.

Так как работа у меня была тестовая и срочная, не столько на знание ADO, сколько нужно было быстро разобраться с MS SQL и обязательно при помощи стандартных компонентов Delphi6, то насколько это было возможно сделать в сжатые сроки, я пока остановился на решении:

ADODataSet.LockType := ltBatchOptimistic
ADODataSet.UpdateBatch() //по идее

Причем сумел задействовать только чтение и кеширование данных для свободного редактирования "количеств накладной" в сетке.

Обновления же я сделал пока совсем в лоб, обходом датасета в цикле и отправкой команд с помощью рантайм создаваемого TADOCommand. То есть в цикле создаю новые в во временной таблице, а затем одной командой удаляю все старые строки накладной, а новые - перекидываю в накладную при помощи insert into ... select from, а временную таблицу уничтожаю.

Это очень грубое решение, но времени совершенствовать не было, так как у меня было много более важных задач в самой базе данных (поддержка остатков при помощи триггеров, быстрый отчет о движении за период и т.д.).

Я долго бился (и сегодня вечером буду биться), пытаясь все же задействовать отправку методом ADODataSet.UpdateBatch().

Я надеюсь, что мне все же удастся заставить ADO отказаться пытаться вставлять в справочник значение-дубликат при попытке вставить лишь новую строку в накладную.

Хотя меня этот момент уже бесит, если честно. Неужели разработчики самого ADO (или хотя бы дельфийской обертки) не могли сделать что-нибудь традиционное в виде 4 команд (SelectSQL, UpdateSQL, DeleteSQL, RefreshSQL), чтобы программист не мучился столько, пытаясь отговорить ADO делать то, что его вообще никто не просил...

Моя мечта - перейти на компоненты прямого доступа и забыть это все в кошмарном сне.

У меня сейчас новая засада (уже 5-я за трое суток).
Хранимая процедура принимает 3 параметра 2: типа datetime, один типа varchar(50). Процедура строит отчет. В Studio Express отчет прекрасно работает. В дизайн-тайме в ADO при указании параметров в объект-инспекторе тоже работает.
При попытке присвоить параметры рантайм, работает, но отчет выдает нулевые данные. Похоже, что параметры типа DateTime доходят криво.

Я пытался обойтись без параметров вообще.

Если явно присвоить строке CommandText в дизайнере:

SP_MYPROC "20080101", "20081010", "%вася%"

То потом рантайм методом Open отчет будет выведен правильно.

Если же рантайм присвоить ту же самую строку, отчет выводит нули.

CommandText := "SP_MYPROC ""20080101"", ""20081010"", ""%вася%"""


Если бы мне кто-нибудь такое сказал, то я, пожалуй, действительно решил бы, что этот человек либо врет, либо у него с головой что-то не то.


 
kaif ©   (2008-09-10 21:13) [14]

У меня сейчас новая засада (уже 5-я за трое суток).
Хранимая процедура принимает 3 параметра 2: типа datetime, один типа varchar(50). Процедура строит отчет. В Studio Express отчет прекрасно работает. В дизайн-тайме в ADO при указании параметров в объект-инспекторе тоже работает.
При попытке присвоить параметры рантайм, работает, но отчет выдает нулевые данные. Похоже, что параметры типа DateTime доходят криво.

Я пытался обойтись без параметров вообще.

Если явно присвоить строке CommandText в дизайнере:

SP_MYPROC "20080101", "20081010", "%вася%"

То потом рантайм методом Open отчет будет выведен правильно.

Если же рантайм присвоить ту же самую строку, отчет выводит нули.

CommandText := "SP_MYPROC ""20080101"", ""20081010"", ""%вася%"""

Если бы мне кто-нибудь такое сказал, то я, пожалуй, действительно решил бы, что этот человек либо врет, либо у него с головой что-то не то.


Прошу прощения. Это сообщение ошибочно.


 
MsGuns ©   (2008-09-10 21:37) [15]

Используй параметры, которые предварительно считывай из ХП (Parameters.Refresh)



Страницы: 1 вся ветка

Форум: "Базы";
Текущий архив: 2009.05.17;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.51 MB
Время: 0.004 c
3-1220965928
kaif
2008-09-09 17:12
2009.05.17
ADO Delphi и транзакции MSSQL


2-1238668101
Den
2009-04-02 14:28
2009.05.17
Туплю с ini-файлом. Чтение значений


15-1236764505
desc
2009-03-11 12:41
2009.05.17
Функция возвращения пути


15-1234352551
Правильный$Вася
2009-02-11 14:42
2009.05.17
2 вопроса по установке D2009


15-1237228271
AlexDan
2009-03-16 21:31
2009.05.17
Тактовая частота.





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский