Конференция "Начинающим" » Кроме Locate что использовать для поиска записи в TDataSet?
 
  • Abcdef123 © (13.01.17 09:21) [0]
    Здравствуйте, Мастера!
    Прошу прощения за тривиальный вопрос.
    Обычно я использую таблицу или запрос, и тогда быстрый поиск можно делать по индексу функцией 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;
 
Конференция "Начинающим" » Кроме Locate что использовать для поиска записи в TDataSet?
Есть новые Нет новых   [118606   +36][b:0][p:0.006]