Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2002.11.18;
Скачать: CL | DM;

Вниз

Как настрить МастерДетайл виды в QuantumGrid v.4 через TADOQuery   Найти похожие ветки 

 
mvg_first ©   (2002-10-28 21:46) [0]

Вышел значит недвано новая версия Quantum Grid от DevExpress. И вней есть такая очень красивая возможность по реализации несколькоих Мастер-Дейил отношений в одном гриде. У кого нибудь получилось уже настроить нормальную работу используюя TADOQuery и параметризированные запросы.
Во всех моих попытках получался глюк выражающийся в отражении одинаковых изменений во всех детаилах при редактировании данных в одном из них. Никто не сталкивался с такой проблемой? Как с этим бороться?


 
vuk ©   (2002-10-28 21:58) [1]

Master-detail построить получилось. Насчет измененяемых датасетов пока проверить не успел. Сегодня попинаю еще - отпишу.


 
Ученик ©   (2002-10-28 22:19) [2]

Дополнительный вопрос:
Master-Detail работает только для GridMode = False или что-то все-таки можно настроить ?


 
vuk ©   (2002-10-28 22:24) [3]

Я, честно говоря, не вижу причин по которым не должен работать Master-Detail не в GridMode. Это же не группировки, где необходимо вытягивание всего набора данных. Хотя... Это я тоже до кучи проверю.
Если честно, давно не приходилось запускать QuantumGrid не в режиме LoadAllRecords (GridMode в QG4). :o)


 
Ученик ©   (2002-10-28 22:28) [4]

>vuk © (28.10.02 22:24)
А как решается проблема быстродействия на больших данных, загрузка это же время


 
vuk ©   (2002-10-28 22:36) [5]

>А как решается проблема быстродействия на больших данных
Большие объемы данных (на которых все это будет действительно тормозить) запрашивать не имеет смысла, поскольку пользователь не сможет в них ориентироваться. Ну сами посудите, кому охота ковыряться в паре тысяч записей выискивая одну (хотя даже пара тысяч записей втягивается в момент)? Поэтому если пользователю реально необходимо работать с большими объемами, то представление данных нужно оптимизировать так, чтобы информация была каким-либо образом структурирована(тот же master-detail). В этом случае никаких проблем больших объемов просто не возникает. А если же нужен некий отчет, то здесь в любом случае нужно ждать полной обработки набора данных.


 
Ученик ©   (2002-10-28 22:41) [6]

>vuk © (28.10.02 22:36)
Как раз и хотелось основную таблицу в GridMode=True, подчиненные в любом виде (карточка, таблица), но почему-то подчиненные оказываются пустыми :(


 
vuk ©   (2002-10-28 22:45) [7]

У меня с этим проблем не было (Master-detail делался исключительно средствами QG4 с использовыанием ADOStoredProc).
Как Вы организуете Master-Detail? Поподробнее, если можно.


 
Ученик ©   (2002-10-28 23:56) [8]

>vuk © (28.10.02 22:45)
GridMode был в каком режиме ? тут ведь вот было: GridMode=False для Master, все показывается нормально, GridMode=True, подчиненные таблицы пустые :(


 
Tornado ©   (2002-10-29 07:57) [9]

А где можно взять новую версю Квантума? Я слышал что эти компоненты стоят немалых денег.


 
Ученик ©   (2002-10-29 08:42) [10]

>Tornado © (29.10.02 07:57)
На www.torry.net продают


 
mvg_first ©   (2002-10-29 10:21) [11]

Ну так что? Кто нибудь уже решил вопрос?
Кстати со всеми почитал я тут ответы и запутался с определениями :) Давайте расставим точки над и.
GridMode - это режим когда загружается только часть данных, он призван ускорить загрузку "непомерно" больших объемов данных.
LoadAllRecords - это когда GridMode = False, в этом режиме доступны и сортировка и группировка и все прочие фенечки :). Хотя в хелпе написано что в GridMode = True сортировку и группировку необходимо организовывать с помощью соответствующих событий.
Есть еще свойство DataInSQLMode - которое определяет что работа происходит с параметризированным запросом. В моем понимании это нечто вроде этого

SELECT * FROM Customers WHERE CUSTID = :ID

Т.е. при работе моей программы достаточно только менять значение параметра и все должно отражаться правильно. По крайней мере есил механизм Мастер_детаил организовывать через Свойство DataSource в TADOQuery то все именно так и работает.
Что подразумевали разработчики QG4 я не знаю.

В примерах QG4 отражается банальная работа с помощью таблиц. И без параметризированых запросов.А как работать именно с запросами?? Я не знаю.


 
mvg_first ©   (2002-10-29 10:32) [12]

Более подробно опишу пример на котором у меня не работает Мастер-Детаил.
Есть две таблицы одна - "Таблица товаров" вторая таблица документов по которым этот товар приходил. Обе достаточно большие больше 10000 записей. Вернее в первой таблице их около 2000 во второй соответственно что то около 20 000. Т.е. открытие этих таблиц полностью занятие достаточно геморойное, как вы понимаете.

По этому написал пример в котором Использую параметрический запрос, все сделал как описано в Хелпе. Даже обработал событие OnDetailFirst, что бы обрабатывать установку параметра для фильрования записей.
Запрос ко второй таблице выглядит так

SELECT * FROM TabDoc WHERE IdTov = :ID_TOV

В обработчике указанного события выполняю переоткрытие таблицы

with (ADataSet as TADOQuery) do
begin
DisableControls;
try
Active := False;
Parameters.ParamByName("ID_TOV").Value := AMasterDetailKeyValues;
Active := True;
finally
EnableControls;
end;
AReopened := True;
end;

В результате вполне красиво по "плюсику" открываются детаилы для каждой строки товара. но при установке курсора ячейку с автоматическим включением редактирование в редактируемом поле отображается значение из другого детаила, который был открыт ранее. И когда начинаю редактировать поле, данные изменяются во всех открытых детаилах в той строке на который был в каждом из них последний раз.


 
vuk ©   (2002-10-29 11:13) [13]

to Ученик:
>тут ведь вот было: GridMode=False для Master, все показывается
>нормально, GridMode=True, подчиненные таблицы пустые :(
Похоже все-таки да, не работает это все в GridMode. Что это, особенность работы или баг, пока не знаю, надо будет DevExpress трясти на эту тему...


to mvg_first:
>Давайте расставим точки над и.
Вы поняли все совершенно верно.

Там же есть нужно написать обработчик OnDetailIsCurrentQuery, который определяет, является ди текущий набор данных в подчиненном наборе данных именно тем набором, который нужно отобразить. Проверяется это по значениям пареметров (в принципе, можног и не проверять, а просто вернуть false). Возможно это решит проблему.


 
mvg_first ©   (2002-10-29 11:46) [14]

Нмчего не помогает, я даже больше скажу. Только что внимательнее присмотрелся к поведению Детаил-грида. У меня стоят параметры по умолчанию, т.е. ДатаСет в авторедактировании, у грида стоит опция "сразу показывать редактор". Так вот, открываю первый детаил грид в нем допустим 5 строк, на первой записи в колонке цена указано 0,91 на второй вижу 0,86 при перемещении фокуса на вторую строку в ней значение меняется на 0,91. Т.е. значение берется из первой записи, и так при хождении по всем строкам :(
Это 100% глюк. Если это не так, скажите как сделать правильно.

Второй глюк который я заметил - это если не ставить галку в свойстве DetailInSQLMode и организовывать мастердетаил используюя TAdoQuery то в детаилах отображается только первая запись хотя их конкретно больше.

Вот такой глюк.


 
mvg_first ©   (2002-10-29 11:47) [15]


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

А вы это сами проверяли? У меня вот не сработало почему то :(


 
vuk ©   (2002-10-29 12:04) [16]

to mvg_first:
>Нмчего не помогает, я даже больше скажу.
У меня такого не было. Все работает как часы (если не в GridMode).


>А вы это сами проверяли? У меня вот не сработало почему то :(
А то как же? Вот только что еще раз проверил. Все работает как и должно.

А у Вас свойства KeyFieldNames/ MasterKeyFieldNames/ DetailKeyFieldNames правильно установлены?


 
mvg_first ©   (2002-10-29 12:17) [17]

Все стоит правильно.
Первая таблица - Все по умолчанию, только установил DataSource на TAdoQuery с запросом SELECT * FROM TovTab (т.е. полная выборка) это таблица мастер. У нее же установил DetailInSQLMode=true.
Добавил подуровень и в в нем в установил DataSource на TAdoQuery с запросом SELECT * FROM DocTab WHERE IdTov = :ID_TOV (т.е. параметризированный запрос).
Свойство DetailKeyFieldNames Установил на поле IdTov - в моей таблице указывает на идентификатор товара
Свойство MasterKeyFieldNames установил на поле ID - поле из первой таблицы указывает на уникальный идентификатор товара
Свойство KeyFieldNames установил на поле ROW_ID - поле второй таблицы указывает на уникальный идентификторо строки во втрой таблице


 
vuk ©   (2002-10-29 12:22) [18]

У Вас BD какая? Если MSSQL, то могу попробовать набросать пример на демонстрационной базе MS и сюда выложить...


 
mvg_first ©   (2002-10-29 12:34) [19]

БД у меня MSSQL 7.0 Насчет примера возражать не буду. Так что б уж совесем все понятно стало.

Может у меня версия QG4 не корректная :) Надо бы сверить :) У меня версия 1.0.0.0


 
mvg_first ©   (2002-10-29 13:57) [20]

Алло vuk так где же пример? Или очень сложно?


 
vuk ©   (2002-10-29 14:58) [21]

Оно не сложно, в принципе, я его уже сделал, просто я сейчас занят на работе... Там только одна тонкость вылезла, которой сразу не заметил (возможно это небольшой баг). Дело в том, что уже загруженный подчиненный набор данных переоткрывается не при активизации соответствующего GridView, а только после навигации по записям в нем.

Пример будет чуть позжее...


 
vuk ©   (2002-10-29 18:22) [22]

Собственно пример. D6 + ADO. Сначала модуль, потом файл формы.
Необходимо поправить ConnectionString.

unit1.pas


unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, cxStyles, cxCustomData, cxGraphics, cxFilter, cxData, cxEdit,
DB, cxDBData, cxGridLevel, cxClasses, cxControls, cxGridCustomView,
cxGridCustomTableView, cxGridTableView, cxGridDBTableView, cxGrid, ADODB,
Grids, DBGrids;

type
TForm1 = class(TForm)
ADOConnection1: TADOConnection;
qryCategories: TADOQuery;
qryProducts: TADOQuery;
dsCategories: TDataSource;
dsProducts: TDataSource;
tvCategories: TcxGridDBTableView;
lvCategories: TcxGridLevel;
cxGrid1: TcxGrid;
qryCategoriesCategoryID: TAutoIncField;
qryCategoriesCategoryName: TWideStringField;
qryCategoriesDescription: TMemoField;
qryCategoriesPicture: TBlobField;
qryProductsProductID: TAutoIncField;
qryProductsProductName: TWideStringField;
qryProductsSupplierID: TIntegerField;
qryProductsCategoryID: TIntegerField;
qryProductsQuantityPerUnit: TWideStringField;
qryProductsUnitPrice: TBCDField;
qryProductsUnitsInStock: TSmallintField;
qryProductsUnitsOnOrder: TSmallintField;
qryProductsReorderLevel: TSmallintField;
qryProductsDiscontinued: TBooleanField;
lvProducts: TcxGridLevel;
tvProducts: TcxGridDBTableView;
tvCategoriesCategoryID: TcxGridDBColumn;
tvCategoriesCategoryName: TcxGridDBColumn;
tvCategoriesDescription: TcxGridDBColumn;
tvCategoriesPicture: TcxGridDBColumn;
tvProductsProductID: TcxGridDBColumn;
tvProductsProductName: TcxGridDBColumn;
tvProductsSupplierID: TcxGridDBColumn;
tvProductsCategoryID: TcxGridDBColumn;
tvProductsQuantityPerUnit: TcxGridDBColumn;
tvProductsUnitPrice: TcxGridDBColumn;
tvProductsUnitsInStock: TcxGridDBColumn;
tvProductsUnitsOnOrder: TcxGridDBColumn;
tvProductsReorderLevel: TcxGridDBColumn;
tvProductsDiscontinued: TcxGridDBColumn;
DBGrid1: TDBGrid;
DBGrid2: TDBGrid;
procedure ReopenProducts(
Sender: TcxDBDataModeController; ADataSet: TDataSet;
const AMasterDetailKeyFieldNames: String;
const AMasterDetailKeyValues: Variant; var AReopened: Boolean);
function CheckProductsDS(
Sender: TcxDBDataModeController; ADataSet: TDataSet;
const AMasterDetailKeyFieldNames: String;
const AMasterDetailKeyValues: Variant): Boolean;
procedure FormCreate(Sender: TObject);
private
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.ReopenProducts(
Sender: TcxDBDataModeController; ADataSet: TDataSet;
const AMasterDetailKeyFieldNames: String;
const AMasterDetailKeyValues: Variant; var AReopened: Boolean);
begin
with (ADataSet as TADOQuery) do
begin
if Parameters.ParamValues["Category"] = AMasterDetailKeyValues then

begin
First;
Exit;
end;
DisableControls;
try
Active := False;
Parameters.ParamValues["Category"] := AMasterDetailKeyValues;
Active := True;
finally
EnableControls;
end;
AReopened := True;
end;
end;

function TForm1.CheckProductsDS(
Sender: TcxDBDataModeController; ADataSet: TDataSet;
const AMasterDetailKeyFieldNames: String;
const AMasterDetailKeyValues: Variant): Boolean;
begin
Result := false;
end;


procedure TForm1.FormCreate(Sender: TObject);
begin
qryCategories.Open;
qryProducts.Open;
end;

end.



 
vuk ©   (2002-10-29 18:24) [23]

unit1.dfm

object Form1: TForm1
Left = 347
Top = 151
Width = 605
Height = 460
Caption = "Form1"
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = "MS Sans Serif"
Font.Style = []
OldCreateOrder = False
OnCreate = FormCreate
PixelsPerInch = 96
TextHeight = 13
object cxGrid1: TcxGrid
Left = 0
Top = 0
Width = 597
Height = 193
Align = alClient
TabOrder = 0
object tvCategories: TcxGridDBTableView
DataController.DataSource = dsCategories
DataController.DetailKeyFieldNames = "CategoryID"
DataController.Filter.Criteria = {00000000}
DataController.KeyFieldNames = "CategoryID"
DataController.Summary.DefaultGroupSummaryItems = <>
DataController.Summary.FooterSummaryItems = <>
DataController.Summary.SummaryGroups = <>
OptionsBehavior.ImmediateEditor = False
object tvCategoriesCategoryID: TcxGridDBColumn
DataBinding.FieldName = "CategoryID"
end
object tvCategoriesCategoryName: TcxGridDBColumn
DataBinding.FieldName = "CategoryName"
end
object tvCategoriesDescription: TcxGridDBColumn
DataBinding.FieldName = "Description"
end
object tvCategoriesPicture: TcxGridDBColumn
DataBinding.FieldName = "Picture"
end
end
object tvProducts: TcxGridDBTableView
DataController.DataModeController.DetailInSQLMode = True
DataController.DataModeController.OnDetailFirst = ReopenProducts
DataController.DataModeController.OnDetailIsCurrentQuery = CheckProductsDS
DataController.DataSource = dsProducts
DataController.DetailKeyFieldNames = "CategoryID"
DataController.Filter.Criteria = {00000000}
DataController.KeyFieldNames = "ProductID"
DataController.MasterKeyFieldNames = "CategoryID"
DataController.Summary.DefaultGroupSummaryItems = <>
DataController.Summary.FooterSummaryItems = <>
DataController.Summary.SummaryGroups = <>
OptionsBehavior.ImmediateEditor = False
object tvProductsProductID: TcxGridDBColumn
DataBinding.FieldName = "ProductID"
end
object tvProductsProductName: TcxGridDBColumn
DataBinding.FieldName = "ProductName"
end
object tvProductsSupplierID: TcxGridDBColumn
DataBinding.FieldName = "SupplierID"
end
object tvProductsCategoryID: TcxGridDBColumn
DataBinding.FieldName = "CategoryID"
end
object tvProductsQuantityPerUnit: TcxGridDBColumn
DataBinding.FieldName = "QuantityPerUnit"
end
object tvProductsUnitPrice: TcxGridDBColumn
DataBinding.FieldName = "UnitPrice"
end
object tvProductsUnitsInStock: TcxGridDBColumn
DataBinding.FieldName = "UnitsInStock"
end
object tvProductsUnitsOnOrder: TcxGridDBColumn
DataBinding.FieldName = "UnitsOnOrder"
end
object tvProductsReorderLevel: TcxGridDBColumn
DataBinding.FieldName = "ReorderLevel"
end
object tvProductsDiscontinued: TcxGridDBColumn
DataBinding.FieldName = "Discontinued"
end
end
object lvCategories: TcxGridLevel
GridView = tvCategories
object lvProducts: TcxGridLevel
GridView = tvProducts
end
end
end
object DBGrid1: TDBGrid
Left = 0
Top = 313
Width = 597
Height = 120
Align = alBottom
DataSource = dsProducts
TabOrder = 1
TitleFont.Charset = DEFAULT_CHARSET
TitleFont.Color = clWindowText
TitleFont.Height = -11
TitleFont.Name = "MS Sans Serif"
TitleFont.Style = []
end
object DBGrid2: TDBGrid
Left = 0
Top = 193
Width = 597
Height = 120
Align = alBottom
DataSource = dsCategories
TabOrder = 2
TitleFont.Charset = DEFAULT_CHARSET
TitleFont.Color = clWindowText
TitleFont.Height = -11
TitleFont.Name = "MS Sans Serif"
TitleFont.Style = []
end


 
vuk ©   (2002-10-29 18:25) [24]

продолжение unit1.dfm

object ADOConnection1: TADOConnection
Connected = True
ConnectionString =
"Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security In" +
"fo=False;Initial Catalog=Northwind;Data Source=FCS---S05"
LoginPrompt = False
Provider = "SQLOLEDB.1"
Left = 32
Top = 70
end
object qryCategories: TADOQuery
Connection = ADOConnection1
CursorType = ctStatic
Parameters = <>
SQL.Strings = (
"SELECT CategoryID, CategoryName, Description, Picture"
"FROM Categories")
Left = 32
Top = 98
object qryCategoriesCategoryID: TAutoIncField
FieldName = "CategoryID"
ReadOnly = True
end
object qryCategoriesCategoryName: TWideStringField
FieldName = "CategoryName"
Size = 15
end
object qryCategoriesDescription: TMemoField
FieldName = "Description"
BlobType = ftMemo
end
object qryCategoriesPicture: TBlobField
FieldName = "Picture"
end
end
object qryProducts: TADOQuery
Connection = ADOConnection1
CursorType = ctStatic
Parameters = <
item
Name = "Category"
DataType = ftString
Size = 4
Value = Null
end>
SQL.Strings = (
"SELECT ProductID, ProductName, SupplierID, "
" CategoryID, QuantityPerUnit, UnitPrice,"
" UnitsInStock, UnitsOnOrder, ReorderLevel, Discontinued"
"FROM Products"
"WHERE CategoryID = :Category")
Left = 32
Top = 126
object qryProductsProductID: TAutoIncField
FieldName = "ProductID"
ReadOnly = True
end
object qryProductsProductName: TWideStringField
FieldName = "ProductName"
Size = 40
end
object qryProductsSupplierID: TIntegerField
FieldName = "SupplierID"
end
object qryProductsCategoryID: TIntegerField
FieldName = "CategoryID"
end
object qryProductsQuantityPerUnit: TWideStringField
FieldName = "QuantityPerUnit"
end
object qryProductsUnitPrice: TBCDField
FieldName = "UnitPrice"
Precision = 19
end
object qryProductsUnitsInStock: TSmallintField
FieldName = "UnitsInStock"
end
object qryProductsUnitsOnOrder: TSmallintField
FieldName = "UnitsOnOrder"
end
object qryProductsReorderLevel: TSmallintField
FieldName = "ReorderLevel"
end
object qryProductsDiscontinued: TBooleanField
FieldName = "Discontinued"
end
end
object dsCategories: TDataSource
DataSet = qryCategories
Left = 60
Top = 98
end
object dsProducts: TDataSource
DataSet = qryProducts
Left = 60
Top = 126
end
end



 
mvg_first ©   (2002-10-29 20:08) [25]

Ок, пример себе скопировал, но посмотрю уже завтра. И вопросы понятное дело завтра продолжаться :)


 
vuk ©   (2002-10-29 20:13) [26]

Когда будете смотреть, обратите внимания на два обычных (TDBGrid) грида внизу формы. Они там для того, чтобы было видно, что происходит с наборами данных при навигации по QG.


 
mvg_first ©   (2002-10-30 12:11) [27]

Вообщем как я и предполагал, глюк остался :)
Как повторить чтоб было понятнее.
Пример скомпилил без изменений (только подправил имя сервера)
Запустил, все заработало, гриды открываются, как положено.
Нажал, на "плюсик" в строке с CategoryId = 4
и так же нажал на "плюсик" в строке с CategoryId = 5
Передо мной картина из двух вложенных таблиц содержащих совершенно разные данные. Как и должно быть. Т.е. пока все нормально.

После чего изменяю знчение в колонке UnitPrice второго детаила в первой строке. После изменения нажимаю Enter и вижу ту же значение в первой строке первого детаила. В результате - явная бочина. Может это так и должно быть??? Но я никогда не докажу этого пользователям моей программы :)


 
mvg_first ©   (2002-10-30 12:18) [28]

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

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

Если перейти обратно в первый детаил все становится на свои места :) Значения возвращаются в норму :).


 
vuk ©   (2002-10-30 14:47) [29]

Да, действительно, баг присутствует, я просто даже сначала на него внимания не обратил. Надо будет багрепорт отправить...


 
mvg_first ©   (2002-10-30 14:59) [30]

Все таки я добился своего !!! Хоть кто то баг подтвердил.

А можно ли считать багом то что в GridMode = True не работает мастер детаил???

И если можно, результат общения мне на мыло mvgfirst@nm.ru если не затруднит.

Заранее спасибо :)


 
vuk ©   (2002-10-30 15:05) [31]

>А можно ли считать багом то что в GridMode = True не работает
>мастер детаил???
Не знаю, пока с этим вопрос не ясен, в ньюсгруппе у DevExpress уже есть сообщения по этому поводу...

Результат (если он будет) можно будет смотреть там же. Пока же нужно еще на это время найти.




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

Текущий архив: 2002.11.18;
Скачать: CL | DM;

Наверх




Память: 0.58 MB
Время: 0.018 c
14-59365
V.exeR
2002-10-28 06:55
2002.11.18
Forum Reader


14-59388
Number 1
2002-10-17 03:10
2002.11.18
Не может быть!!!


1-59197
siliks330
2002-11-09 09:27
2002.11.18
Как сделать текст.редактор, для работы с очень большими текстами?


3-59044
John13
2002-10-29 12:40
2002.11.18
Мощная заморочка для знатоков SQL! Помогите плз


1-59192
^Sanya
2002-11-09 14:19
2002.11.18
Кто найдёт ошибку(ки) в этом коде?