Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Базы данных и репортинг > Класс производный от TOracleQuery


Автор: holodnaya 11.12.2008, 02:08
Здравствуйте, уважаемые!
Я столкнулась со следующей проблемой. Мне нужно в отдельном модуле описать класс, производный от TOracleQuery, таким образом, чтобы его методы были доступны в других модулях программы.
Пишу вот так:

Код

TLogon = class(TOracleQuery)

   private

   public
   procedure Authory;

   constructor Create (AOwner: TComponent);
end;

var  Logon: TLogon;

implementation


uses  UDM;

 constructor TLogon.Create (AOwner: TComponent);
 begin
    Inherited;
     Session:=DM.OracleSession1;
   end;

 procedure TLogon.Authory ;
 var
 Query: String;
 begin

    // вставка текста запроса и описание переменных только при первом вызове
    if Query = '' then
    begin

      DeclareVariable('Account', otString);
      DeclareVariable('Passw', otString);
      
    //... и там ещё часть кода...



Первое, на что ругается Делфи - это следующая строка.
 
Код

Session:=DM.OracleSession1;


Потом ему не нравится строка, в которой объявляется переменная 'Passw'
Мне непонятно почему. Session - это свойство класса TOracleQuery и при наследовании оно должно тоже передаваться дочернему классу. Методы определения переменных (DeclareVariable) тоже есть в родительском классе.
Что я делаю не так? Можно ли вообще создавать класс таким образом, как указано выше (по сути, только конструктор добавляется, а процедуры остаются те же самые) или это некорректное объявление и процедуры (подобные DeclareVariable) надо объявлять в разделе public и описывать ниже?

Автор: pseud 11.12.2008, 10:27
какой ужас   smile 
я бы за такой код сделал тебя горячей
для начала:
Код

type
  TLogonOracleQuery = class(TOracleQuery)
   private
   public
     constructor Create (AOwner: TComponent);
     procedure Authory;
  end;

implementation

constructor TLogonOracleQuery.Create (AOwner: TComponent);
begin
  inherited;
  if AOwner is TOracleSession then
    Session := TOracleSession(AOwner);
end;

procedure TLogonOracleQuery.Authory ;
var
  sSQL: string;
begin

  // вставка текста запроса и описание переменных только при первом вызове
  if sSQL = '' then
  begin
    DeclareVariable('Account', otString); // что ето? и что за ошибка?
    DeclareVariable('Passw', otString); // что ето? и что за ошибка?


Автор: holodnaya 11.12.2008, 11:42
Ну хорошо. Я описываю конструктор таким образом.
А как его вызвать из другой формы, например, формы авторизации (FormLogon), причём OracleSession1 находится в отдельном DataModule, а не на форме авторизации.

Код

type
  TFormLogon = class(TForm)
    GroupBox1: TGroupBox;
    LabeledEdit1: TLabeledEdit;
    LabeledEdit2: TLabeledEdit;
    BitBtn1: TBitBtn;
    BitBtn2: TBitBtn;
    procedure BitBtn1Click(Sender: TObject);
    procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure BitBtn2Click(Sender: TObject);
  private
    { Private declarations }
  public
    Logon: TLogonOracleQuery;

    { Public declarations }
  end;

procedure TFormLogon.BitBtn1Click(Sender: TObject);
begin
      Logon.Create(FormLogon);

      // авторизация пользователя
      Logon.Authory;
end;




Такая запись будет правильной?

Автор: pseud 11.12.2008, 12:07
Logon - не давай таких имен
Код

TLabel - lblName, lblDesc
TEdit - edtName...
TQuery - quAccounts...


что-то типа этого:
Код

...
  quLogon: TLogonOracleQuery;
...

procedure TFormLogon.BitBtn1Click(Sender: TObject);
begin
  if quLogon = nil then
    quLogon := TLogonOracleQuery.Create(ТвойМодуль.ТвойСешн);
  
  quLogon.Authory;
end;

Автор: holodnaya 11.12.2008, 13:40
С конструктором разобрались smile  Спасибо большое за помощь!
Теперь перейдём к другому моменту.
Что касается этих строк
Код

DeclareVariable('Account', otString); // что ето? и что за ошибка?
DeclareVariable('Passw', otString); // что ето? и что за ошибка?

то при процедурном программировании , эти методы я использовала для определения переменных
Код

OracleQuery1.DeclareVariable('Account', otString); 
OracleQuery1.DeclareVariable('Passw', otString); 

 
Сейчас мне как эти переменные опредеклять? Попробовала следующим образом
Код

 procedure TLogonOracleQuery.Authory (Account: String; Passw: String);
 var
 sSQL: String;
 begin

    // вставка текста запроса и описание переменных только при первом вызове
    if sSQL = '' then
    begin

        sSQL:= 'SELECT Pole1, pole2, t2.pole3 FROM table1 t1, table2 t2 WHERE ' +
              'lower(account) = lower('+Account+') AND lower(passw) = lower('+Passw+') AND ' +
              't1.pole3 = t2.pole3';

      SQL.Clear;
      SQL.Add(sSQL);

    end;

    Execute;

    // если запрос ничего не вернул, то авторизация не пройдена
    if Eof then
      // выдать ошибку
      ShowMessage('Неверные имя пользователя или пароль')

    // иначе - авторизация пройдена
    else
       begin
        Close;
        // показать главную форму
        MainForm.Show;
        // уничтожить форму авторизации
        FormLogon.Free;

       end;

 end;


И при вызове этой процедуры из другого модуля пишу, откуда записываются данные в переменные "Account" и "Passw"
Код

quLogon.Authory (LabeledEdit1.Text, LabeledEdit2.Text);


Вообще можно ли при определении процедуры класса так много там всего написать?
И сейчас выдает ошибку на строке 
Код

SQL.Clear;

Смысл ошибки такой, что обращается по одному адресу, а читается другой

Автор: pseud 11.12.2008, 18:18
Цитата(holodnaya @  11.12.2008,  13:40 Найти цитируемый пост)
И сейчас выдает ошибку на строке 

скроее всего на строке Execute, т.к. параметры ты забыла в кавычки взять.
Authory - нет такого слова в английском языке.
наверно этот код ты случайно сбда впаяла. он видимо написан в форме. 
Код

begin
  Close;
  // показать главную форму
  MainForm.Show;
  // уничтожить форму авторизации
  FormLogon.Free;
end;


попробуй так:
Код

type
  TLogonOracleQuery = class(TOraQuery)
   private
   public
     constructor Create(AOwner: TComponent);
     function Logon(AUser: string; APassword: string): Boolean;
  end;

implementation

constructor TLogonOracleQuery.Create(AOwner: TComponent);
begin
  inherited;
  if AOwner is TOraSession then
    Session := TOraSession(AOwner);
end;

function TLogonOracleQuery.Logon(AUser: string; APassword: string): Boolean;
begin
  Result := False;

  Active := False;
  SQL.Clear;
  SQL.Add('SELECT <поля>');
  SQL.Add('FROM table1 t1, table2 t2');
  SQL.Add('WHERE lower(t1.account) = lower(' + QuotedStr(AUser) + ')');
  SQL.Add('AND lower(t1.passw) = lower(' + QuotedStr(APassword) + ')');
  SQL.Add('AND t1.pole3 = t2.pole3');
  Active := True;

  Result := (not IsEmpty);

  if Result = False then
    Application.MessageBox('Неверные имя пользователя или пароль', 'Авторизация', MB_ICONWARNING);

end.

и так в форме
Код

procedure TForm1.Button1Click(Sender: TObject);
begin

  if quLogon = nil then
    quLogon := TLogonOracleQuery.Create(ТвойМодуль.ТвойСешн);

  if quLogon.Logon(LabeledEdit1.Text, LabeledEdit2.Text) then
    ............
end;

Автор: holodnaya 12.12.2008, 02:04
Я использвоала предложенный вариант кода, но писалась ошибка, что Active, IsEmpty - неопределённые идентификаторы.
Вопрос: почему создаваемый класс не перенимает свойства от родительского класса TOracleQuery? Может быть, их надо переопределять?
Заменила 
Код

function TLogonOracleQuery.Logon(AUser: string; APassword: string): Boolean;
  begin
  Result := False;

  Close;
  SQL.Clear;
  SQL.Add('SELECT <поля>');
  SQL.Add('FROM table1 t1, table2 t2');
  SQL.Add('WHERE lower(t1.account) = lower(' + QuotedStr(AUser) + ')');
  SQL.Add('AND lower(t1.passw) = lower(' + QuotedStr(APassword) + ')');
  SQL.Add('AND t1.pole3 = t2.pole3');
  Execute;
  Close;

  Result := (not IsEmpty);

  if Result = False then
    Application.MessageBox('Неверные имя пользователя или пароль', 'Авторизация');


Сейчас пишет, что идентификатор IsEmpty не определён.

Автор: pseud 12.12.2008, 12:36
Цитата(holodnaya @  12.12.2008,  02:04 Найти цитируемый пост)
Вопрос: почему создаваемый класс не перенимает свойства от родительского класса TOracleQuery?

честно говоря, у меня нет такого класса  smile 
кто ето? что за библиотека? какая версия дельфи?

Добавлено через 3 минуты и 19 секунд
Цитата(holodnaya @  12.12.2008,  02:04 Найти цитируемый пост)
Сейчас пишет, что идентификатор IsEmpty не определён.


IsEmpty - это паблик функция класса TDataSet - базового класса всех наборов данных.

Код

function TDataSet.IsEmpty: Boolean;
begin
  Result := FActiveRecord >= FRecordCount;
end;


предположу, что твой TOracleQuery - не наследник этого класса, а жаль.

Добавлено через 4 минуты и 38 секунд
тогда замени на
Код

Result := (RecordCount > 0);

или
Код

Result := (RecordCount = 1);

Автор: holodnaya 12.12.2008, 13:04
Пишу на Делфи из Borland Developer Studio 2006. 
TOracleQuery - объект из компонентов прямого доступа Direct Oracle Access, который устанавливается дополнительно.
При этом используется библиотека Oracle.

Автор: pseud 12.12.2008, 15:06
Цитата(holodnaya @  12.12.2008,  13:04 Найти цитируемый пост)
Пишу на Делфи из Borland Developer Studio 2006. 
TOracleQuery - объект из компонентов прямого доступа Direct Oracle Access, который устанавливается дополнительно.
При этом используется библиотека Oracle.


я использую Oracle Data Access Components (ODAC).
раз твой TOracleQuery не знает функциии IsEmpty - следую моим рекомендация в пред. посте

Автор: holodnaya 12.12.2008, 18:03
Цитата(pseud @ 12.12.2008,  15:06)

раз твой TOracleQuery не знает функциии IsEmpty - следую моим рекомендация в пред. посте

К сожалению, этого он тоже не знает.

Автор: pseud 12.12.2008, 18:59
Цитата(holodnaya @  12.12.2008,  18:03 Найти цитируемый пост)
К сожалению, этого он тоже не знает.


т.е. он не может определить количества отобранных записей???

Автор: holodnaya 12.12.2008, 20:43
Цитата(pseud @ 12.12.2008,  18:59)

т.е. он не может определить количества отобранных записей???

да, не может определить количесвто записей.
 Нашла, как можно определить
 
Код

Result := (RowCount>0);

 Но всё равно выделяет строку SQL.Clear;, а до закоментирования строки Close, при ошибке ссылался на неё в функции
Код

function TLogonOracleQuery.Logon(AUser: string; APassword: string): Boolean;
  begin
  Result := False;

  //Close;
  SQL.Clear;
  SQL.Add('SELECT ceh1, zp, kl.user_id');
  SQL.Add('FROM karmen_access ka, karmen_login kl');
  SQL.Add('WHERE lower(account) = lower(' + QuotedStr(AUser) + ')');
  SQL.Add('AND lower(passw) = lower(' + QuotedStr(APassword) + ')');
  SQL.Add('AND ka.user_id = kl.user_id');
  Execute;
  Close;

   Result := (RowCount>0);

  if Result = False then
    Application.MessageBox('Неверные имя пользователя или пароль', 'Авторизация');
end;

Такое впечатление, что действительно свойства не наслёдуются.
И ещё, я так понимаю, что по иерархий классов (по аналогии с обычными TQuery TDateset) TOracleQuery от TOracleDataSet должен наследовать некоторые свойства и методы.

Автор: pseud 15.12.2008, 10:15
Цитата(holodnaya @  12.12.2008,  20:43 Найти цитируемый пост)
Такое впечатление, что действительно свойства не наслёдуются.

тогда извини
нет у меня такого класса
пальцем в небо не получилось

Автор: holodnaya 16.12.2008, 01:07
Цитата(pseud @ 15.12.2008,  10:15)

пальцем в небо не получилось

И что же теперь делать? Использовать другие компоненты?
Что касается ODAC, где это можно взять?

Автор: pseud 16.12.2008, 10:28
Цитата(holodnaya @  16.12.2008,  01:07 Найти цитируемый пост)
И что же теперь делать?


Ссылка:
http://www.sql.ru/forum/actualthread.aspx?tid=466437

Все точки расставлены:
Код

//unit OracleData
TOracleDataset = class(TDataSet);

//unit Oracle
TOracleQuery = class(TComponent)

попробуй cделать свой класс так:
Код

  TLogonOracleDataSet = class(TOracleDataset)
  ... 

Автор: holodnaya 17.12.2008, 09:43
Pseud, спасибо большое за помощь!
Я разобралась в чём у меня была ошибка.
Это я по глупости вызывала конструктор в одной процедуре (при загрузке MainForm), а методы этого класса - в процедуре другого юнита, а не в одной процедуре одного мейна последовательно.
Сейчас пишу так, и всё работает. 
Код

procedure TFLogon.BitBtn1Click(Sender: TObject);
begin
    if quLogon = nil then
    quLogon := TLogonOracleQuery.Create(DM.OracleSession1);
    
   if quLogon.Logon(LabeledEdit1.Text, LabeledEdit2.Text) then
     begin
       MainForm.Show;
        // уничтожить форму авторизации
        FLogon.Free;
        //quLogon.Free;
     end;
 end;

Автор: pseud 17.12.2008, 11:08
предлагаю немножко еще доработать:
1. я так понял quLogon это поле класса формы, а не брошенный на форму компонент. может лучше вообще динамически.
2. FLogon - это видимо глобальная переменная автогенерируемая дельфей. в классе формы НИКОГДА к ней не обращайся. лучше уж к Self. 
3. поэтому код:
Код

procedure TFLogon.BitBtn1Click(Sender: TObject);
begin
  with TLogonOracleQuery.Create(DM.OracleSession1) do
  try
    if Logon(LabeledEdit1.Text, LabeledEdit2.Text) then
    begin
      MainForm.Show;
      Close; // закрытие Self
    end;
  finally
    Free; // не забываем подгребать мусор TLogonOracleQuery
  end;
end;

4. всем всем всем и тебе в частности пройти http://www.delphikingdom.com/quintana/quintana.asp. Вся прелесть в том, что результат тестирования - это не выставление оценки знаниям, а подробный и доходчивый анализ ответов на поставленный вопросы.


Автор: holodnaya 17.12.2008, 21:32
Спасибо и за оптимизацию, и за предложение пройти тестирование. Обязательно проверю свои силы как только сдам сессию.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)