![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Один DataSet - два курсора [D5, IB6.x, Paradox]
-=GUEST=- © (2003-10-21 17:27:00)
Давно мучает одна проблема.
Допустим есть грид, подключенный к DataSet"у.
На этой же форме есть DBLookupComboBox, который ведет выборку по аналогичному Dataset"у.
Приходится создавать два одинаковых DataSet(Выполнять один и тот же запрос дважды)
Есть ли возможность сделать один Dataset, а навигация по нему осуществляется разными курсорами - независимо в Гриде и LookupComboBox
-=GUEST=- (2003-10-22 15:08:00) [1]
В любой умной книжке описана разница между TQuery и TTable и все её знают.
Не важно как грузит TQuery(TQuery для примера взято - что бы указать что используется не TTable, для IB вообще FIBPLus используется - тут будет меньше споров кто как фетчит ).
Это детали. В другом проблема.
Vlad (2003-10-22 14:51:00) [2]
>TP (22.10.03 14:49) [30]
TQuery грузит столько записей сколько настроено в БДЕ алиасе или столько сколько отфетчит юзер.
TP (2003-10-22 14:49:00) [3]
Похоже мы в детском саду: TQuery грузит столько записей, сколько записей в базе удолетворяет условиям запроса. А TDBGrid отображает столько записей, сколько записей уместится в высоте TDBGrid.
-=GUEST=- (2003-10-22 14:39:00) [4]
>TP (22.10.03 14:18) [27]
Мы же не в детском саду. Если Вы подключите TDBGrid к TQuery, то он будет грузить столько записей, сколько потребует TDBGrid для отображения. Т.е. если опустить детали грузит записи все-таки грид, точнее "требует" их у набора данных
А по поводу кто кого потомок Вы объясняли еще в начале топика.
ПРОБЛЕМА заставить ClientDataSet загружать записи по запросу от грида. Или какое-то подобное решение.
Nikolay M. (2003-10-22 14:26:00) [5]
> грид загружает записи по необходимости
Данные загружает DataSet, плюс фетчить все или по частям - зависит от используемых компонент.
А то, что есть необходимость фетчить 400 000 записей - неправильно идеологически. Ты что, хочешь довести до инфаркта юзера, предложив ему список в почти поллимона записей?
TP (2003-10-22 14:18:00) [6]
TDBGrid ни когда не загружал записи. Во все времена записи грузились в TDataSet и его потомков. TDBGrid только отображает записи из TDataSet.По крайней мере так было до сегодняшнего дня.
-=GUEST=- (2003-10-22 14:13:00) [7]
>Nikolay M. © (22.10.03 13:52) [25]
По поводу DBLookupComboBox утверждать не буду, но вот грид загружает записи по необходимости, да и LookupComboBox должен делать точно также. А то выходит ты раскрываешь его и тут фэтчится в примеру 400 000 записей - не логично как-то.
Вспомогательный запрос я постоянно и использую. Но как написано в теме топика - "Давно мучает одна проблема" - зачем выполнять два разных запроса, загружать одну и туже информацию (даже если фетчатся только необходимые записи - выходит ~трафик*2, а если будет Paradox то и поболее) если можно найти способ "клонирования" курсора. ClientDataSet практически решает эту проблему.
Nikolay M. (2003-10-22 13:52:00) [8]
> -=GUEST=- (22.10.03 12:05) [20]
> >Nikolay M. © (22.10.03 11:23) [19]
> В идеале должно было бы:
> 1. Загрузка позиций по запросу, а не все сразу (допустим
> там пару тыся записей с картинками)
> 2. Раздельная навигация.
А как по-твоему, в DBLCB тогда появятся ВСЕ записи, если не фетчить их все? Сделай тогда вспомогательный запрос, в котором будет селект одного нужного поля и пихай его в DB(Lookup)ComboBox.
TP (2003-10-22 13:29:00) [9]
У TDataSetProvider.Option есть значение poAutoRefres.
В D5 это неработает однозначно, в D6,7 не знаю, ещё не пробовал.
Так что проблему автоматического обновления запроса я решал при помощи COM-ика с событием, которое при изменении данных на сервере срабатывало у клиентов.
Но это всё делалось при помощи MIDAS.
-=GUEST=- (2003-10-22 12:41:00) [10]
Может по исходникам и так, но в хелпе:
Call CloneCursor to share the data belonging to another client dataset.
Последняя проблема - возможно ли заставить ClientDataSet загружать данные по надобности
>TP (22.10.03 12:23) [22] но зачем нужен TSuperDataSet
Ну это для примера.
Можно сказать что TSuperQuery = TDataSetProvider, а TSuperDataSet = TClientDataSet
Но чтобы Sharing Data - а не создание копии(а Вы говорите это происходит по исходникам), и Fetch-On-Demand для этого самого Shared Data.
TP (2003-10-22 12:23:00) [11]
Метод CloneCursor TClientDataSet не создаёт второй курсор.
Он создаёт копию "родителя".(см. исходники).
Полбзователей конечно надо уважать, но зачем нужен TSuperDataSet,
я так и не понял.
-=GUEST=- (2003-10-22 12:13:00) [12]
В ClientDataSet есть ф-ция CloneCursor, кот. позволяет шарить одни данные между двумя(и более) ClientDataSet. Если еще решить проблему с фэтчем по запросу.
Опять таки в ClientDataSet есть с-во FetchOnDemand - но оно желаемого результата не дает.
-=GUEST=- (2003-10-22 12:05:00) [13]
>Nikolay M. © (22.10.03 11:23) [19]
В идеале должно было бы:
1. Загрузка позиций по запросу, а не все сразу (допустим там пару тыся записей с картинками)
2. Раздельная навигация.
ClientDataSet - не решает первого. Т.е. качает все сразу.
>TP (22.10.03 11:12) [18]
... не заниматься ерундой. Измени логику программы ...
Есть множество задач в кот. удобно иметь два одинаковых DataSet"a
И удобно не с точки зрения программиста, а для работы пользователя - к удобству которого в конечном итоге и стоит стремится.
Решение проблемы на мой взгляд выглядит так.
Есть какой-то объект, допустим "TSuperQuery" - осущ. непосредстненную работу с базой данных.
К нему подключ. "TSuperDataSet"+DataSource+TDBGrid(или любой виз. комп.).
TSuperDataSet - осуществляет навигацию по TSuperQuery и имеет свой курсор. Если для TSuperDataSet нужны данные, кот. нет в TQuery - он их фэтчит, причем если эти же данные запросит другой TSuperDataSet - повторного фэтча не будет.
Такой херни наверно нету.
Nikolay M. (2003-10-22 11:23:00) [14]
Да брось тогда ты этот DBLCB. Возьми простой DBComboBox и заполни его Items-ы руками - просто и сурово :)
TP (2003-10-22 11:12:00) [15]
Это не недостаток. Это принцип работа TDataSet.
Нет запроса нет данных.
Что бы в TClienDataset обновились данные, необходимо закрыть
TDataset, снова открыть и повторить клонирование.
Можно обойтись и без TClienDataset.
Например так:
function TDM.Clone(DS: TADODataSet): TADODataSet;
begin
if not DS.Active then DS.Open;
Result:= TADODataSet.Create(Self);
with Result do begin
CommandText:= DS.CommandText;
Connection:= DS.Connection;
Parameters.Assign(DS.Parameters);
Open;
end;
end;
А лучше не заниматься ерундой. Измени логику программы, что бы
не было проблемы "Один DataSet - два курсора"
-=GUEST=- (2003-10-22 10:52:00) [16]
>TP (22.10.03 09:05) [16]
Спасибо, работает.
Единственный недостаток - ClientDataSet фэтчик все данные из DataSet"a, а не загружает по необходимости. На больших запросах, наверное, лучше все таки изпользовать два аналогичных Query.
TP (2003-10-22 09:05:00) [17]
> -=GUEST=- (21.10.03 18:37) [12]
Не очень понятно, что происходит.
Я клонирую TDataSet так:
function GetData(ADataSet: TDataSet): OleVariant;
begin
with TDatasetProvider.Create(nil) do
try
Dataset:= ADataset;
Result:= Data;
finally
Free;
end;
end;
procedure TForm1.Button1Click(Sender:TObject);
begin ClientDataset1.Data;= GetData(ADODataset1); end;
Конечно к этому времени ADODataset.Active:= True
После этого ADODataset можешь Close, можешь Free. По барабану.
Получена копия, с которой можешь делать, что хочешь.
AlexGreG (2003-10-22 08:42:00) [18]
А мне про лень понравилась шутка :)))
MsGuns (2003-10-21 20:21:00) [19]
>Vlad © (21.10.03 18:19) [11]
>Ну уж эт ты загнул.
Ничего я не загнул. Так и есть.
>Многофункциональные компоненты тоже имеют свои минусы :)
Конечно, вертолетом сложнее управлять чем самокатом.
-=GUEST=- (2003-10-21 18:44:00) [20]
Такое впечатление, что ClientDataSet при своем открытии открывает Query, скачивает из него все данные(видно по подключенному к Query гриду), а потом закрывает его.
Не совсем то чего хотелось бы.