Конференция "Начинающим" » ошибка Exception EAccessViolation in module Project1.exe [D7, WinXP]
 
  • sasha198407 © (22.03.12 21:32) [0]
    Доброго времени суток. Создаю в делфи7 программно Fields для ADOQuery, код ниже.


    procedure TForm1.FormCreate(Sender: TObject);
    var
    tfil:TStringField;
    begin
    ADOQuery1.SQL.Clear;
    ADOQuery1.SQL.Add('SELECT login, password, id_roles');
    ADOQuery1.SQL.Add('FROM account');
    tfil:=TStringField.Create(ADOQuery1);
    tfil.FieldName      :='login';
    tfil.DataSet         :=ADOQuery1;
    tfil.SetFieldType(ftString);
    tfil.DisplayLabel  :='Логин';
    tfil.DisplayWidth :=15;
    tfil.FieldKind       :=fkData;
    ADOQuery1.Fields.Add(tfil);
    DBGrid1.Columns.Add.FieldName:='login';
    ADOQuery1.Open;
    ADOQuery1.Active:=true;
    end;



    Созданное поле выводится отлично, но при закрытие формы появляется ошибка
    Exception EAccessViolation in module Project1.exe at 000E4918. Access violation at address 004E4918 in module 'Project1.exe'. Read of address 01AF93E0.

    Ошибка исчезает, если закоментировать строку
    ADOQuery1.Fields.Add(tfil);



    У меня вопрос, почему такая хрень и что с ней делать.
    И второй вопрос как вывести все поля?
    Заранее спасибо.
  • Ega23 © (23.03.12 08:22) [1]

    >  но при закрытие формы появляется ошибка


    Что показывает отладчик?

    ADOQuery1.Open;
    ADOQuery1.Active:=true;



    Зачем?
  • Anatoly Podgoretsky © (23.03.12 08:37) [2]
    ADOQuery1.SQL.Add('SELECT login, password, id_roles');
    {
    tfil:=TStringField.Create(ADOQuery1);
    tfil.FieldName      :='login';
    tfil.DataSet         :=ADOQuery1;
    tfil.SetFieldType(ftString);
    tfil.DisplayLabel  :='Логин';
    tfil.DisplayWidth :=15;
    tfil.FieldKind       :=fkData;
    ADOQuery1.Fields.Add(tfil);
    DBGrid1.Columns.Add.FieldName:='login';
    }
    ADOQuery1.Open;
  • sasha198407 © (23.03.12 09:21) [3]
    Anatoly Podgoretsky
    Я согласен, что для вывода всех полей проще всего сделать запрос SELECT. Но дело в том, что я планирую создать программно lookup поле, а для этого необходимо описать Fields. А т.к. подключение к БД происходит программно, я вынужден делать это в тексте программы.
  • sasha198407 © (23.03.12 09:23) [4]
    При компиляции ничего не показывает, но проблема явно в этой строке
    ADOQuery1.Fields.Add(tfil);

  • sniknik © (23.03.12 09:29) [5]
    > планирую создать программно lookup поле, а для этого необходимо описать Fields
    зачем "необходимо описать"? почему не подходит автосозданное Fields?
  • Inovet © (23.03.12 09:35) [6]
    > [4] sasha198407 ©   (23.03.12 09:23)
    > При компиляции ничего не показывает

    Отладчиком пользуются не при компиляции.
  • Anatoly Podgoretsky © (23.03.12 09:35) [7]
    > sasha198407  (23.03.2012 09:21:03)  [3]

    Ну так создавай ВСЕ поля.
  • Cobalt © (23.03.12 10:04) [8]
    Два поля с именем login?
    мсье определенно знает толк в извращениях.
  • sasha198407 © (23.03.12 10:17) [9]
    Напишу по-подробнее.

    Есть БД на MSSQL в ней 2 таблицы account и roles
    account
    id_account int
    name1 vchar
    login vchar
    password vchar
    id_roles int

    roles
    id_roles int
    roles vchar

    таблицы соединены по полю id_roles
    В delphi вывожу таблицу account через DBGrid. Хочу что бы в DBGrid отображалось поле roles в виде выпадающего списка. Применяю для этого lookup. Но т.к. подключение к БД происходит в процессе выполнения программы, то пришлось описать lookup программно. Если код такой


    procedure TFCreateUsers.FormCreate(Sender: TObject);
    begin
       DataModule1.ADOQuery2.SQL.Clear;
    //вывод таблицы roles
       DataModule1.ADOQuery2.SQL.Add('SELECT * FROM roles');
       DataModule1.ADOQuery2.Open;

    //закрытие запросов
       DataModule1.ADOQuery1.SQL.Clear;
    //вывод таблицы account
       DataModule1.ADOQuery1.SQL.Add('SELECT name1,login,password,id_roles');
       DataModule1.ADOQuery1.SQL.Add('FROM account');
       DataModule1.ADOQuery1.Open;
    //описываем lookup
                FieldName  := '3role';
                FieldKind  := fkLookup;
                DataSet    := DataModule1.ADOQuery1;
                Name       := 'ADOQuery1Field3role';
               KeyFields  := 'id_roles';
               LookUpDataSet := DataModule1.ADOQuery2;
               LookUpKeyFields := 'id_roles';
               LookUpResultField:= 'roles';
               DataModule1.ADOQuery2.FieldDefs.Add(Name, ftString, 20, false);
    //активируем ADOQuery2
      DataModule1.ADOQuery2.Active:=true;
    //активируем ADOQuery1
      DataModule1.ADOQuery1.Active:=true;
    //привязываем колонки в DBGrid1 к полям таблицы account
       DBGrid1.Columns[0].FieldName:='name1';
       DBGrid1.Columns[1].FieldName:='login';
       DBGrid1.Columns[2].FieldName:='password';
       DBGrid1.Columns[3].FieldName:='3role';
    end;


    , то выпадает ошибка: 'ADOQuery4: Field 'id_roles' not found'
    Отсюда делаю вывод, что Fields надо описывать программно.
    Начинаю добавлять, пишу к примеру

    tfil:=TStringField.Create(ADOQuery1);
    tfil.FieldName      :='login';
    tfil.DataSet         :=ADOQuery1;
    tfil.SetFieldType(ftString);
    tfil.DisplayLabel  :='Ëîãèí';
    tfil.DisplayWidth :=15;
    tfil.FieldKind       :=fkData;
    ADOQuery1.Fields.Add(tfil);
    DBGrid1.Columns.Add.FieldName:='login';

       tfil.FieldName      :='password';
       tfil.DataSet         :=ADOQuery1;
       tfil.SetFieldType(ftString);
       tfil.DisplayLabel  :='Ïàðîëü';
       tfil.DisplayWidth :=15;
       tfil.FieldKind       :=fkData;
       ADOQuery1.Fields.Add(tfil);
       DBGrid1.Columns.Add.FieldName:='password';


    , т.е. добавляю поля login и password, то он выводит эти поля, но показывает записи только последнего поля, т.е. поля password, а при закрытие окна выводит ошибкаписи только последнего поляу
    Exception EAccessViolation in module Project1.exe at 000E4918. Access violation at address 004E4918 in module 'Project1.exe'. Read of address 01AF93E0.
    Комментирую
    ADOQuery1.Fields.Add(tfil);

    и меняю
    DBGrid1.Columns.Add.FieldName

    на
    DBGrid1.Columns[i].FieldName

    , где i порядковый индекс колонки. Ошибка при закрытие исчезает, но по прежнему выводит записи только последнего поля.
  • sasha198407 © (23.03.12 10:20) [10]

    > Два поля с именем login?

    Имеете ввиду строки?

    ADOQuery1.Fields.Add(tfil);
    DBGrid1.Columns.Add.FieldName:='login';

  • Ega23 © (23.03.12 10:29) [11]

    > Отсюда делаю вывод, что Fields надо описывать программно.


    Вот. Из-за неверного подхода и неверно сделанного вывода начинаем строить монстроподобное страхоуё..ще.
  • sasha198407 © (23.03.12 10:32) [12]

    > Вот. Из-за неверного подхода и неверно сделанного вывода
    > начинаем строить монстроподобное страхоуё..ще.

    Какой вариант
  • sniknik © (23.03.12 10:36) [13]
    найти ошибку, не делая выводов.
  • sniknik © (23.03.12 10:38) [14]
    > найти ошибку
    в смысле, не в том что уже наворочено из-за неверного, а в самом первом коде.
  • Inovet © (23.03.12 11:11) [15]
    Я так и не понял, почему нелязя всё сделать в дизайнере.

    Несколько полей в лукап разделяются знаком ";".
  • sasha198407 © (23.03.12 11:33) [16]

    > Я так и не понял, почему нелязя всё сделать в дизайнере.

    А как сделать в дизайне, если подключение к БД происходит в тексте программы, а значит и ADOQuery начинает выполняться в программе.
  • Inovet © (23.03.12 11:45) [17]
    > [16] sasha198407 ©   (23.03.12 11:33)
    > если подключение к БД происходит в тексте программы

    Подключить в дизайнере, настроить, оключить.
  • Inovet © (23.03.12 11:47) [18]
    И за пользование TADOQuery сейчас поругают.
  • Ega23 © (23.03.12 11:57) [19]

    > А как сделать в дизайне, если подключение к БД происходит
    > в тексте программы, а значит и ADOQuery начинает выполняться
    > в программе.


    Написать нужные поля. То, что оно ошибку подключения выдаёт - ну и хрен с ней. Напиши эти поля в блокноте, скопируй, вставь.
  • sasha198407 © (23.03.12 13:04) [20]
    Сделал как Ega3 посоветовал, заработало. Конечно немного неудобно, да и хрен с ним, результат меня устраивает. Всем спасибо, тему можно закрывать.
 
Конференция "Начинающим" » ошибка Exception EAccessViolation in module Project1.exe [D7, WinXP]
Есть новые Нет новых   [134431   +13][b:0][p:0.003]