Мастера DELPHI, Delphi programming community Рейтинг@Mail.ru Титульная страница Поиск, карта сайта Написать письмо 
| Новости |
Новости сайта
Поиск |
Поиск по лучшим сайтам о Delphi
FAQ |
Огромная база часто задаваемых вопросов и, конечно же, ответы к ним ;)
Статьи |
Подборка статей на самые разные темы. Все о DELPHI
Книги |
Новинки книжного рынка
Новости VCL
Обзор свежих компонент со всего мира, по-русски!
|
| Форумы
Здесь вы можете задать свой вопрос и наверняка получите ответ
| ЧАТ |
Место для общения :)
Орешник
Коллекция курьезных вопросов из форумов
Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / rsdn.org

 
Чтобы не потерять эту дискуссию, сделайте закладку « предыдущая ветвь | форум | следующая ветвь »

Кроме Locate что использовать для поиска записи в TDataSet?


Abcdef123 ©   (13.01.17 09:21

Здравствуйте, Мастера!
Прошу прощения за тривиальный вопрос.
Обычно я использую таблицу или запрос, и тогда быстрый поиск можно делать по индексу функцией FindKey, к примеру.
Сейчас хочу создать форму-Lookup - своего рода шаблон с гридом, чтобы показывать данные, возможность выбрать нужную запись и закрыть форму. При открытии формы (как вариант) надо становиться на запись по заданному значению ключа (если значение ключа передано как параметр, к примеру). Вот как то так.
Поскольку этот шаблон я буду использовать для таблиц TadsTable, а также запросов TadsQuery, то думаю, что правильнее для работы с данными на форме использовать  TDataSet. Но, только уж очень медленно работает Locate.
1.Я читала на форуме, что некоторые программисты вообще Locate не используют. А что в таком случае?
2.А может вообще идея насчет использовать TDataSet в моем случае не самый оптимальный вариант?
3.И еще, почему то в XE8 Locate с опцией loCaseInsensitive у меня не работает, выбает ошибку AV. В версии D2007 работает нормально. Пока я могу использовать без этой опции, но хотелось бы узнать, это XE версии баг или что то только у меня?
Хотелось бы услышать коммертарии на все три вопроса.
(Для уточнения, работаю с Advantage).
Заранее спасибо!


sniknik ©   (13.01.17 10:11[1]

> очень медленно работает Locate.
Locate тоже использует индекс, если он есть, если нет то перебором. т.е. чуть более универсально чем FindKey. а вот то что медленно... как напишешь, с учетом специфики используемого, от функций обычно не зависит.

> что некоторые программисты вообще Locate не используют.
некоторые и дельфи не используют, не нужен он им... и что же в таком случае?

> А может вообще идея насчет использовать TDataSet в моем случае не самый оптимальный вариант?
оптимальность "в вакууме" это вообще миф, для одного действия что-то оптимально для другого нет. зависит от того, что ты делаешь в "твоем случае". хотя в принципе датасет для обработки данных вполне оптимален.

> почему то в XE8 Locate с опцией loCaseInsensitive у меня не работает, выбает ошибку AV. В версии D2007 работает нормально.
чисто предположительно, причина в тебе конечно, как написал, но и в юникоде еще, раз один и тот же код без его поддержки работает, с поддержкой -ошибка. его ты не учел.

> работаю с Advantage
важное уточнение, он вроде еще файл-сервер? т.е. напрямую с таблицей работает? тогда если таблица в расшарке то наскорость работы влияет сеть, Locate перечитывает файл при переборе, и т.д. у всего свои особенности.


Inovet ©   (13.01.17 10:40[2]

> [1] sniknik ©   (13.01.17 10:11)
> важное уточнение, он вроде еще файл-сервер?

Там два варианта файл серверный и клиент серверный.


Inovet ©   (13.01.17 10:57[3]

> [0] Abcdef123 ©   (13.01.17 09:21)
> я буду использовать для таблиц TadsTable, а также запросов
> TadsQuery, то думаю, что правильнее для работы с данными
> на форме использовать  TDataSet

Что за ерунда? TAdsTable и есть потомок TDataSet. Идеологически в Advantage TAdsTable как раз и подойдёт для выбора из справочника в гриде. Locate вполне себе нормальный метод, только индексы необходимые должны быть для скорости. Ну и кроме того есть более явный поиск по индексу как у TAdsTable, так и у TAdsQuery
AdsSeek
В TAdsQuery можно после открытия создать необходимые индексы. В случае файл серверного доступа stADS_LOCAL, физически выборка и индексы будут расположены для ускорения в локальной папке %TEMP%.


Inovet ©   (13.01.17 10:58[4]

Из справки

CAUTION The AdsSeek method is not any slower nor any less efficient than the native Delphi equivalent FindKey and FindNearest methods. But in nearly every single situation, the native Delphi methods FindKey and FindNearest are easier to use. It is recommended that the Advantage extended method AdsSeek only be used when absolutely necessary. See your Delphi documentation for more information about the FindKey and FindNearest Delphi methods.


sniknik ©   (13.01.17 11:01[5]

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


Inovet ©   (13.01.17 11:24[6]

> [5] sniknik ©   (13.01.17 11:01)

Ну я выше написал про TAdsQuery. Это всё прозрачно работает, я сервером не пользовался, но достаточно поменять метод доступа, и должно всё стать клиент-серверным "теоретически".
Два наследника всего, что для локального, что для серверного одни и те же TAdsTable и TAdsQuery. Причём TAdsTable не есть что-то неправильное.


Abcdef123 ©   (13.01.17 12:25[7]

To [1] >Locate тоже использует индекс, если он есть, если нет то перебором. т.е. чуть более универсально чем FindKey. а вот то что медленно... как напишешь, с учетом специфики используемого, от функций обычно не зависит.
Вы имеете в виду физический индекс в таблице? Он есть, Locate искользую именно по этому полю, но все равно медленно.
> чисто предположительно, причина в тебе конечно, как написал, но и в юникоде еще, раз один и тот же код без его поддержки работает, с поддержкой -ошибка. его ты не учел.
Я думала, что в юникоде дело, поэтому значение ключа как Locate параметр прописываю как Вариант значение, хотя поле в таблице строковое. А как правильно надо?


Abcdef123 ©   (13.01.17 12:29[8]

To [6]. Так я ничего не имею против TAdsTable и TAdsQuery. Просто в данном примере, если рассматривать форму как шаблон с передаваемым параметром данных могут быть 2 варианта (TAdsTable и TAdsQuery), как я в таком случае на форме должна оперировать-различать?


Token ©   (13.01.17 14:26[9]

Различать можно

 if DataSet is TAdsTable then


Inovet ©   (13.01.17 14:53[10]

> [8] Abcdef123 ©   (13.01.17 12:29)
> как я в таком случае на форме должна оперировать-различать?

Для поиска с помощью Locate различать не надо - метод есть и там и там.

Если медленно, значит всё-таки индекс не задействован. Попробуй для начала проще сделать - с TAdsTable - и посмотреть на скорость поиска. Насчёт AV потом разобраться - должно нормально работать.


Inovet ©   (13.01.17 15:03[11]

Как индекс создан?


sniknik ©   (13.01.17 15:03[12]

> Вы имеете в виду физический индекс в таблице?
я имею ввиду существующий... даже если он есть физический, в таблице, но ты сделал запрос в клиент-серверном стиле, то на клиент придут "голые" данные, индексы останутся на сервере, т.е. не будут существовать без их создания уже локально (если поддерживается компонентами).

> параметр прописываю как Вариант значение
вариант это не тип, это "контейнер" разных типов, типа универсально, но на самом деле зависит от реализации. я бы лучше использовал тип AnsiString (или преобразование к нему), хотя опять же, зависит в каком виде данные у в таблице... может нужно наоборот.

> А как правильно надо?
не бывает правильно "в вакууме", только применительно к чему то, причем попытка перенести на другое тут же делает его неправильным.


Inovet ©   (13.01.17 15:15[13]

И сразу ещё вопросы.
Таблицы какие - родные для Ads ADT, FoxPro CDX, VPF или может Clipper NTX?
И какая кодовая страница?


Abcdef123 ©   (13.01.17 15:39[14]

to [13] Таблицы FoxPro CDX, коды OEM


sniknik ©   (13.01.17 15:47[15]

> коды OEM
вах

> я бы лучше использовал тип AnsiString
беру свой слов обратн.

... хотя ..., компоненты преобразование делают?


Inovet ©   (13.01.17 15:47[16]

> [14] Abcdef123 ©   (13.01.17 15:39)

Понятно. А индекс как создан?
Индексное выражение какое?


Inovet ©   (13.01.17 15:48[17]

> [15] sniknik ©   (13.01.17 15:47)
> компоненты преобразование делают?

Делают


Inovet ©   (13.01.17 16:14[18]

Ещё на всякий случай, хоть на скорость поиска это и не должно влиять. В файле
adslocal.cfg
есть такие строчки?
ANSI_CHAR_SET=Russian
OEM_CHAR_SET=RUSSIAN

и файлы
ansi.chr
extend.chr

и вообще все файлы быблиотеки 10 штук из специально для этого имеющейся паки Redistribute должны быть расположены в путях поиска и быть одной версии ADS. Для проверки стоит попробовать поместить из одного комплекта установки, который и используется в работе, в самый ближайший путь - в папку с исполняемым файлом программы. Мало ли как там и где что раскидано.


Abcdef123 ©   (13.01.17 17:28[19]

to [16] Index  выражение -просто название поля , поле типа String?


sniknik ©   (13.01.17 18:01[20]

> to [16] Index  выражение -просто название поля , поле типа String?
это ты отвечаешь или спрашиваешь? FoxPro CDX позволяет выражения/функции в индексе, а в таблице в Index указывается не название поля, а название индекса. почему и вопрос в [16].


Inovet ©   (13.01.17 21:33[21]

Вот так работает достаточно быстро

Main.pas

unit Main;

interface

uses
 Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
 Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Grids, Vcl.DBGrids,
 Data.DB, adsdata, adsfunc, adstable, adsset, adscnnct;

type
 TForm1 = class(TForm)
   DB: TAdsConnection;
   AdsSettings: TAdsSettings;
   tbStreet: TAdsTable;
   dsStreet: TDataSource;
   dbgrStreet: TDBGrid;
   btCreateIdx: TButton;
   btDropIdx: TButton;
   btLocate: TButton;
   edKey: TEdit;
   qTmp: TAdsQuery;
   procedure FormCreate(Sender: TObject);
   procedure btCreateIdxClick(Sender: TObject);
   procedure btDropIdxClick(Sender: TObject);
   procedure btLocateClick(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

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

procedure TForm1.btCreateIdxClick(Sender: TObject);
begin
 // Если таблицы добавить в словарь данных,
 // то можно выполнять запрос без TAdsQuery
 // DB.Execute('...');

 // Можно создавать индекс методом TAdsTable TAdsQuery
 // AdsCreateIndex

 // Обычный синтаксис
 {
 qTmp.SQL.Text :=
   'CREATE INDEX NAME ON STREET (NAME);';
 }

 // Для индексных выражений FoxPro
 // Здесь строка в индексе сразу приводится к верхнему регистру
 qTmp.SQL.Text :=
   'EXECUTE PROCEDURE sp_CreateIndex90(''STREET.DBF'', ''STREET.CDX'', ''NAME'', ''UPPER(NAME)'', '''',  2, 512, NULL);';
 tbStreet.Close;
 try begin
   qTmp.ExecSQL;
   qTmp.SQL.Clear;
   tbStreet.IndexName := 'NAME';
 end;
 finally
   tbStreet.Open;
 end;
end;

procedure TForm1.btDropIdxClick(Sender: TObject);
begin
 qTmp.SQL.Text :=
   'DROP INDEX STREET.NAME;';
 tbStreet.Close;
 try begin
   qTmp.ExecSQL;
   qTmp.SQL.Clear;
   tbStreet.IndexName := '';
 end;
 finally
   tbStreet.Open;
 end;
end;

procedure TForm1.btLocateClick(Sender: TObject);
begin
 if not tbStreet.Locate('NAME', edKey.Text, [loCaseInsensitive, loPartialKey]) then begin
   ShowMessage('Не найдено');
 end;
end;

end.


Main.dfm


object Form1: TForm1
 Left = 0
 Top = 0
 Caption = 'Ads Test Locate'
 ClientHeight = 461
 ClientWidth = 625
 Color = clBtnFace
 Font.Charset = DEFAULT_CHARSET
 Font.Color = clWindowText
 Font.Height = -11
 Font.Name = 'Tahoma'
 Font.Style = []
 OldCreateOrder = False
 OnCreate = FormCreate
 PixelsPerInch = 96
 TextHeight = 13
 object dbgrStreet: TDBGrid
   Left = 8
   Top = 88
   Width = 609
   Height = 361
   DataSource = dsStreet
   TabOrder = 4
   TitleFont.Charset = DEFAULT_CHARSET
   TitleFont.Color = clWindowText
   TitleFont.Height = -11
   TitleFont.Name = 'Tahoma'
   TitleFont.Style = []
 end
 object btCreateIdx: TButton
   Left = 16
   Top = 16
   Width = 75
   Height = 25
   Caption = 'btCreateIdx'
   TabOrder = 0
   OnClick = btCreateIdxClick
 end
 object btDropIdx: TButton
   Left = 97
   Top = 16
   Width = 75
   Height = 25
   Caption = 'btDropIdx'
   TabOrder = 1
   OnClick = btDropIdxClick
 end
 object btLocate: TButton
   Left = 176
   Top = 16
   Width = 75
   Height = 25
   Caption = 'btLocate'
   TabOrder = 2
   OnClick = btLocateClick
 end
 object edKey: TEdit
   Left = 8
   Top = 61
   Width = 609
   Height = 21
   TabOrder = 3
   Text = #1052#1072#1088#1089
 end
 object DB: TAdsConnection
   ConnectPath = 'D:\WORK\AdsTestLocate'
   AdsServerTypes = [stADS_LOCAL]
   LoginPrompt = False
   StoreConnected = False
   Left = 352
   Top = 8
 end
 object AdsSettings: TAdsSettings
   DateFormat = 'dd.MM.ccyy'
   ShowDeleted = False
   AdsServerTypes = [stADS_LOCAL]
   Left = 400
   Top = 8
 end
 object tbStreet: TAdsTable
   DatabaseName = 'DB'
   StoreActive = False
   AdsConnection = DB
   AdsTableOptions.AdsLockType = Compatible
   AdsTableOptions.AdsCharType = OEM
   TableName = 'STREET'
   TableType = ttAdsCDX
   Left = 456
   Top = 8
 end
 object dsStreet: TDataSource
   DataSet = tbStreet
   Left = 504
   Top = 8
 end
 object qTmp: TAdsQuery
   StoreActive = False
   AdsTableOptions.AdsLockType = Compatible
   AdsTableOptions.AdsCharType = OEM
   SourceTableType = ttAdsCDX
   AdsConnection = DB
   Left = 560
   Top = 8
   ParamData = <>
 end
end


Inovet ©   (13.01.17 21:37[22]

Никаких AV на loCaseInsensitive не было.

Свойство
AdsTableOptions.AdsLockType = Compatible
ставить, если оно надо. Быстрее будет
AdsTableOptions.AdsLockType = Proprietary


Inovet ©   (13.01.17 21:42[23]

Да, забыл. Тестировал на таблице Street из Кладр по полю Name
http://gnivc.ru/inf_provision/classifiers_reference/kladr/
Больше миллиона записей, не то чтобы много, ну и ничё так. Проверь на своих, где медленно работало.


Inovet ©   (13.01.17 21:55[24]

> [21] Inovet ©   (13.01.17 21:33)
> // Если таблицы добавить в словарь данных,
> // то можно выполнять запрос без TAdsQuery
> // DB.Execute('...');

В этом я засомневался, что-то там он будет всё-равно свои ADT пытаться искать. Проверять не хочу. А таблицы лучше всё-таки добавить в словарь.


Abcdef123 ©   (14.01.17 07:20[25]

Извиняюсь за опечатку! Вопроса в моем последнем сообщении не должно быть! Это был ответ. Я имела в виду, что в таблице поле, например FieldName1 String (20), и Index по этому полю FieldName1.


Abcdef123 ©   (14.01.17 07:32[26]

To [24] Должна признаться, что мы работаем чисто с таблицами, словари пока не использовали. Поэтому простите, если вопрос окажется слишком уж примитивным: вот вы сказали "таблицы лучше всё-таки добавить в словарь", если начать испольвать словарь, это значит ВМЕСТО отдельных таблиц, что мы используем сейчас, или ДОПОЛНИТЕЛЬНО, как бы дублируя таблицы в словарь?
To [21] Большое спасибо за приведенный код и все другие комментарии, я в понедельник обязательно всё попробую!


Inovet ©   (14.01.17 11:11[27]

> [26] Abcdef123 ©   (14.01.17 07:32)

Дополнительно, но таблицы не дублируются в словарь, только метаданные. Сами файлы таблиц не изменяются при этом.


Inovet ©   (16.01.17 12:05[28]

Т.е. словарь Data Dictionary в терминологии ADS - это по-другому база данных, там можно создавать триггеры, хранимые процедуры, представления, контроль целостности, ещё кое-какие удобства. Только для старых dbf не из VFP многое не возможно, хотя бы потому, что Primary Key просто так не сделать, потому что в Фоксе уникальный индекс совсем другой смысл уникальности имеет. Ну и вообще, естественно, можно снаружи залезть чем-нибудь и всё испортить.


Inovet ©   (16.01.17 13:12[29]

Перечитал ещё раз свой код. Мелкий ньанс не относящийся к обсуждаемой теме: раз уж подчищаем ресурсы в виде текста запроса, то надо это делать в блоке finally
qTmp.SQL.Clear;


версия для печати

Написать ответ

Ваше имя (регистрация  E-mail 







Разрешается использование тегов форматирования текста:
<b>жирный</b> <i>наклонный</i> <u>подчеркнутый</u>,
а для выделения текста программ, используйте <code> ... </code>
и не забывайте закрывать теги! </b></i></u></code> :)


Наверх

  Рейтинг@Mail.ru     Титульная страница Поиск, карта сайта Написать письмо