Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > Базы данных
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 17.02.2009, 12:38
Аватар для chetaykin
chetaykin chetaykin вне форума
Прохожий
 
Регистрация: 15.02.2009
Сообщения: 13
Репутация: 10
По умолчанию ООП и БД

товарищи давайте обсудим столь интересную тему.
было бы очень интересно узнать кто как подходит к решению данного вопроса.
в книгах пишут про ООП что это круто и здорово, но примеров - просто нет.
взглянуть бы хоть на один исходник, или хотя бы интерфейсную часть
модуля работы с БД.
Я думаю ни одного меня это интересует
Ответить с цитированием
  #2  
Старый 17.02.2009, 12:41
Аватар для Aristarh Dark
Aristarh Dark Aristarh Dark вне форума
Модератор
 
Регистрация: 07.10.2005
Адрес: Москва
Сообщения: 2,906
Версия Delphi: Delphi XE
Репутация: выкл
По умолчанию

Взгляни на adodb.pas
__________________
Некоторые программисты настолько ленивы, что сразу пишут рабочий код.

Если вас наказали ни за что - радуйтесь: вы ни в чем не виноваты.
Ответить с цитированием
  #3  
Старый 17.02.2009, 12:52
Аватар для chetaykin
chetaykin chetaykin вне форума
Прохожий
 
Регистрация: 15.02.2009
Сообщения: 13
Репутация: 10
По умолчанию

типа посмеялся?
да смешно!
с компонентный подходом всё ясно (об этом много говорим), интересен именно ООП
Ответить с цитированием
  #4  
Старый 17.02.2009, 13:09
Аватар для Aristarh Dark
Aristarh Dark Aristarh Dark вне форума
Модератор
 
Регистрация: 07.10.2005
Адрес: Москва
Сообщения: 2,906
Версия Delphi: Delphi XE
Репутация: выкл
По умолчанию

Единственная объектная БД с которой приходилось работать - 1С. И то там все довольно убого. Да и не в топик про нее
__________________
Некоторые программисты настолько ленивы, что сразу пишут рабочий код.

Если вас наказали ни за что - радуйтесь: вы ни в чем не виноваты.
Ответить с цитированием
  #5  
Старый 17.02.2009, 14:02
Аватар для chetaykin
chetaykin chetaykin вне форума
Прохожий
 
Регистрация: 15.02.2009
Сообщения: 13
Репутация: 10
По умолчанию

Да нет. Я не про объектные БД.
Предположим у меня есть класс "Сотрудник" с полями "имя", "фамилия", "должность" и данные будут загружаться из базы, ну и сохраняться понятно тоже будут в ней же.
Так вот как мне заносить/сохранять данные из БД?
бросить на форму какой-нить Connection, прицепить к нему какой-нить DataSet? так чтож здесь от ООП? компоненты и не более.
Ответить с цитированием
  #6  
Старый 17.02.2009, 14:59
Аватар для Aristarh Dark
Aristarh Dark Aristarh Dark вне форума
Модератор
 
Регистрация: 07.10.2005
Адрес: Москва
Сообщения: 2,906
Версия Delphi: Delphi XE
Репутация: выкл
По умолчанию

Значит твой объект "Сотрудник" должен иметь методы сохранения и чтения себя из базы. И разработчик пользующийся этим объектом не должен думать о том что нужно бросить что-то еще на форму
__________________
Некоторые программисты настолько ленивы, что сразу пишут рабочий код.

Если вас наказали ни за что - радуйтесь: вы ни в чем не виноваты.
Ответить с цитированием
  #7  
Старый 17.02.2009, 15:16
Аватар для chetaykin
chetaykin chetaykin вне форума
Прохожий
 
Регистрация: 15.02.2009
Сообщения: 13
Репутация: 10
По умолчанию

Есть консэнсус!
Собственно об этом и тема!
Как это реализовать? В класс запихивать Connection и DataSet?
это не выход.
Ну вот как например ты делаешь? есть у тебя подобный опыт?
Ответить с цитированием
  #8  
Старый 17.02.2009, 18:57
Аватар для Aristarh Dark
Aristarh Dark Aristarh Dark вне форума
Модератор
 
Регистрация: 07.10.2005
Адрес: Москва
Сообщения: 2,906
Версия Delphi: Delphi XE
Репутация: выкл
По умолчанию

Ну Connection конечно пихать в класс не стоит, можно передавать его в конструктор при создании. А вот DataSet'ы различные можно реализовать и внутри класса.
__________________
Некоторые программисты настолько ленивы, что сразу пишут рабочий код.

Если вас наказали ни за что - радуйтесь: вы ни в чем не виноваты.
Ответить с цитированием
  #9  
Старый 18.02.2009, 08:43
Аватар для chetaykin
chetaykin chetaykin вне форума
Прохожий
 
Регистрация: 15.02.2009
Сообщения: 13
Репутация: 10
По умолчанию

А как поступать когда класс содержит в себе другой класс, а он в свою очередь еще...
пример: класс "Район" содержит в себе класс "Муниципальное образование", в нем есть класс "Населенный пункт" в котором есть "Улица". Понятно каждый класс работает с БД. Передаем Connection в "Район" а он в свою очередь раздает всем остальным? Ты считаешь не коряво выходит?
Ответить с цитированием
  #10  
Старый 18.02.2009, 08:46
Аватар для chetaykin
chetaykin chetaykin вне форума
Прохожий
 
Регистрация: 15.02.2009
Сообщения: 13
Репутация: 10
По умолчанию

...а вообще было бы здорово посмотреть на чей нибудь исходник...
Ответить с цитированием
  #11  
Старый 18.02.2009, 09:41
Аватар для Aristarh Dark
Aristarh Dark Aristarh Dark вне форума
Модератор
 
Регистрация: 07.10.2005
Адрес: Москва
Сообщения: 2,906
Версия Delphi: Delphi XE
Репутация: выкл
По умолчанию

Цитата:
А как поступать когда класс содержит в себе другой класс, а он в свою очередь еще...
А это называется умным словом инкапсуляция
__________________
Некоторые программисты настолько ленивы, что сразу пишут рабочий код.

Если вас наказали ни за что - радуйтесь: вы ни в чем не виноваты.
Ответить с цитированием
  #12  
Старый 18.02.2009, 09:53
Аватар для chetaykin
chetaykin chetaykin вне форума
Прохожий
 
Регистрация: 15.02.2009
Сообщения: 13
Репутация: 10
По умолчанию

есть исходник? не жадничай - покажи!
Ответить с цитированием
  #13  
Старый 18.02.2009, 11:29
Аватар для chetaykin
chetaykin chetaykin вне форума
Прохожий
 
Регистрация: 15.02.2009
Сообщения: 13
Репутация: 10
По умолчанию

с инкапсуляцией-то всё понятно, спрятать можно всё что угодно. но тему я эту открыл не от того что не знаю как это сделать.
хочу посмотреть (или обсудить) как это делают другие программисты.
ещё раз повторюсь данный вопрос очень скудно освещён, или не освещен вовсе.
Ответить с цитированием
  #14  
Старый 18.02.2009, 13:51
Аватар для Aristarh Dark
Aristarh Dark Aristarh Dark вне форума
Модератор
 
Регистрация: 07.10.2005
Адрес: Москва
Сообщения: 2,906
Версия Delphi: Delphi XE
Репутация: выкл
По умолчанию

Эх, въедливый. Ну да это и не плохо. Что ж, будем писать объектную БД на дельфях. Чисто для обучения.

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

Вот что получилось набросать за последний час рабочего дня
Код:
unit AbstractDB;
{
  Модуль реализующий класс абстрактного движка БД

  Эта БД ничего особого не умеет :)
  Но для примера она нам пригодится

  Работаем только со строками длинной в 250 символов - никаких других типов
  Процедуры чтения и записи данных по индексу в БД
  + процедура пометки записи на удаление
}
interface

uses
  Classes;

const
  DeleteFlag = $FF;  //признак того что данная запись в БД помечена на удаление

type
  TMyRec = string[250];  //Это будет нашей записью
  TAbstractDB = class    //Это класс самого движка
  protected
    FFileName:string;    //Тут имя файла с которым будем работать
    FData:TFileStream;   //Объект для работы с файлом (кстати, тут умное слово ИНКАПСУЛЯЦИЯ)
    FBuffer:array [1..255] of byte;   //Буффер чтения/записи (ПОЧЕМУ длинна буфера не равна длине данных - потому что первые 5 байт будем использовать для системных нужд)
    function ReadData(i:integer):TMyRec;  //Функция реализующая чтение
    procedure WriteData(i:integer;data:TMyRec); //Процедура реализующая запись
  public
    constructor Create (aFileName:string);  //Конструктор
    destructor Destroy; override;           //Деструктор
    procedure Delete (index:integer);       //Процедура ПОМЕТКИ на удаление
    property data[index:integer]:TMyRec read ReadData write WriteData;    //Единственное (пока??) свойство доступа к данным
  end;


implementation

uses SysUtils;

{ TAbstractDB }

constructor TAbstractDB.Create(aFileName: string);
begin
  inherited Create;
  if FileExists(aFileName) then
    FData:=TFileStream.Create(aFileName,fmOpenReadWrite)
  else
    FData:=TFileStream.Create(aFileName,fmCreate);
end;

procedure TAbstractDB.Delete(index: integer);
{
  Пометка записи на удаление
  i - номер записи которую хотим того :)
}
begin
  if FData.Size>=(index-1)*255 then               //проверим не вывалимся ли за границу файла
    begin
      FData.Seek((index-1)*255,soFromBeginning);  //спозиционируем курсор в файле
      FData.ReadBuffer(FBuffer[1],255);           //читаем
      FBuffer[1]:=DeleteFlag;                     //установили пометку
      FData.WriteBuffer(FBuffer[1],255);          //записали назад
    end;
end;

destructor TAbstractDB.Destroy;
begin
  FData.Destroy;    //Файл не забыли грохнуть
  inherited;
end;

function TAbstractDB.ReadData(i: integer): TMyRec;
{
  Чтение данных из базы
  i - номер читаемой записи
  result - наши мега данные :)
}
begin
  if FData.Size>=(i-1)*255 then               //проверим не вывалимся ли за границу файла
    begin
      FData.Seek((i-1)*255,soFromBeginning);  //спозиционируем курсор в файле
      FData.ReadBuffer(FBuffer[1],255);       //читаем
      Move(FBuffer[6],result[1],250);
    end;
end;

procedure TAbstractDB.WriteData(i: integer; data: TMyRec);
{
  Запись данных в БД
  i - номер записи по порядку (нумерация с нуля)
  data - данные
}
begin
  if FData.Size>=(i-1)*255 then               //проверим не вывалимся ли за границу файла
    begin
      FillChar(FBuffer[1],255,#0);            //очистим буффер
      Move(data[1],FBuffer[6],250);           //скопируем в него инфу
      FData.Seek((i-1)*255,soFromBeginning);  //спозиционируем курсор в файле
      FData.WriteBuffer(FBuffer[1],255);      //Запишем данные
    end;
end;

end.

пример использования:
Код:
var
  i:TAbstractDB;
begin
  i:=TAbstractDB.Create('c:\data.ADB');
  i.data[1]:='какой-то там текст';
  i.data[2]:='другой текст';
  ShowMessage(i.data[2]);
  i.Free;
end;

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

Если вас наказали ни за что - радуйтесь: вы ни в чем не виноваты.
Ответить с цитированием
Этот пользователь сказал Спасибо Aristarh Dark за это полезное сообщение:
gerych (14.01.2012)
  #15  
Старый 18.02.2009, 15:01
Аватар для chetaykin
chetaykin chetaykin вне форума
Прохожий
 
Регистрация: 15.02.2009
Сообщения: 13
Репутация: 10
По умолчанию

Шаришь! ничё ни скажешь.
но я все же немного про другое, до своего ADO или dbExpress я еще не дорос
лучше будет если я покажу код, а ты скажешь что в нем не верно

Код:
unit ObjectAdress;

interface

uses ADODB, Contnrs;

type
  TMunicList = class;
  TTownList = class;
  TStreetList = class;

  TAdrObj = class
  private
    FName: string;
    FParent: integer;
    FConnection: TADOConnection;
    FID: integer;
    procedure SetConnection(const Value: TADOConnection);
    procedure SetID(const Value: integer);
    procedure SetName(const Value: string);
    procedure SetParent(const Value: integer);
  public
    property ID: integer read FID write SetID;
    property Name: string read FName write SetName;
    property Connection: TADOConnection read FConnection write SetConnection;
    property Parent: integer read FParent write SetParent;
  end;

  TMunicTown = class(TAdrObj)
  private
    FKadastralNumber: string;
    FOKATO: string;
    procedure SetKadastralNumber(const Value: string);
    procedure SetOKATO(const Value: string);
  public
    property OKATO: string read FOKATO write SetOKATO;
    property KadastralNumber: string read FKadastralNumber write SetKadastralNumber;
  end;

  TAdrList = class(TObjectList)
  private
    DataSet: TADODataSet;
    FParent: integer;
    FConnection: TADOConnection;
    procedure SetConnection(const Value: TADOConnection);
    procedure SetParent(const Value: integer);
  public
    constructor Create;
    property Connection: TADOConnection read FConnection write SetConnection;
    property Parent: integer read FParent write SetParent;
  end;

  TRaion = class(TAdrObj)
  private
    FMunicList: TMunicList;
    procedure SetMunicList(const Value: TMunicList);
    function GetMunicList: TMunicList;
  public
    procedure CreateMunicList;
    property MunicList: TMunicList read GetMunicList write SetMunicList;
  end;

  TMunic = class(TMunicTown)
  private
    FTownList: TTownList;
    procedure SetTownList(const Value: TTownList);
    function GetTownList: TTownList;
  public
    procedure CreateTownList;
    property TownList: TTownList read GetTownList write SetTownList;
  end;

  TTown = class(TMunicTown)
  private
    FStreetList: TStreetList;
    FPrefix: string;
    procedure SetStreetList(const Value: TStreetList);
    procedure SetPrefix(const Value: string);
    function GetStreetList: TStreetList;
  public
    procedure CreateStreetList;
    property Prefix: string read FPrefix write SetPrefix;
    property StreetList: TStreetList read GetStreetList write SetStreetList;
  end;

  TStreet = class(TAdrObj)
  private
    FDocument: string;
    FPrefix: string;
    procedure SetDocument(const Value: string);
    procedure SetPrefix(const Value: string);
  public
    property Document: string read FDocument write SetDocument;
    property Prefix: string read FPrefix write SetPrefix;
  end;

  TRaionList = class(TAdrList)
  protected
    procedure Put(Index: integer; Item: TRaion);
    function Get(Index: integer): TRaion;
  public
    property Items[Index: integer]: TRaion read Get write Put; default;
    function Add(Raion: TRaion): integer;
    procedure ReadFromDB;
  end;

  TMunicList = class(TAdrList)
  protected
    procedure Put(Index: integer; Item: TMunic);
    function Get(Index: integer): TMunic;
  public
    property Items[Index: integer]: TMunic read Get write Put; default;
    function Add(Munic: TMunic): integer;
    procedure ReadFromDB;
  end;

  TTownList = class(TAdrList)
  protected
    procedure Put(Index: integer; Item: TTown);
    function Get(Index: integer): TTown;
  public
    property Items[Index: integer]: TTown read Get write Put; default;
    function Add(Town: TTown): integer;
    procedure ReadFromDB;
  end;

  TStreetList = class(TAdrList)
  protected
    procedure Put(Index: integer; Item: TStreet);
    function Get(Index: integer): TStreet;
  public
    property Items[Index: integer]: TStreet read Get write Put; default;
    function Add(Street: TStreet): integer;
    procedure ReadFromDB;
  end;

implementation

{ TRaionList }

const
  cSQL_GetRaion: string =
    'SELECT id, name FROM adr WHERE lvl = 1';

function TRaionList.Add(Raion: TRaion): integer;
begin
  Result := inherited Add(Raion);
end;

function TRaionList.Get(Index: integer): TRaion;
begin
  if Count -1 >= Index then
    Result := TRaion(inherited Items[Index])
  else
    Result := nil;
end;

procedure TRaionList.Put(Index: integer; Item: TRaion);
begin
  inherited Items[Index] := Item;
end;

procedure TRaionList.ReadFromDB;
var i: integer;
begin
  Clear;
  DataSet.Connection := Self.Connection;
  DataSet.CommandText := cSQL_GetRaion;
  DataSet.Open;
    while not DataSet.Eof do
    begin
      i := Add(TRaion.Create);
      Items[i].Id := DataSet.FieldByName('id').AsInteger;
      Items[i].Name := DataSet.FieldByName('name').AsString;
      Items[i].Connection := Self.Connection;
      Items[i].Parent := Parent;
      Items[i].CreateMunicList;
      DataSet.Next
    end;
  DataSet.Close;
end;

{ TAdrObj }

procedure TAdrObj.SetConnection(const Value: TADOConnection);
begin
  FConnection := Value;
end;

procedure TAdrObj.SetID(const Value: integer);
begin
  FID := Value;
end;

procedure TAdrObj.SetName(const Value: string);
begin
  FName := Value;
end;

procedure TAdrObj.SetParent(const Value: integer);
begin
  FParent := Value;
end;

{ TAdrList }

constructor TAdrList.Create;
begin
  DataSet := TADODataSet.Create(nil);
  self.FParent := 0;
end;

procedure TAdrList.SetConnection(const Value: TADOConnection);
begin
  FConnection := Value;
end;

procedure TAdrList.SetParent(const Value: integer);
begin
  FParent := Value;
end;

{ TMunicTown }

procedure TMunicTown.SetKadastralNumber(const Value: string);
begin
  FKadastralNumber := Value;
end;

procedure TMunicTown.SetOKATO(const Value: string);
begin
  FOKATO := Value;
end;

{ TMunicList }

const
  cSQL_GetMunicFromParent: string =
    'SELECT id, name, okato, kadastr FROM adr WHERE lvl = 2 AND' +
     ' parent_id = :parent_id';

//реализация методов аналогично TRaionList
function TMunicList.Add(Munic: TMunic): integer;

function TMunicList.Get(Index: integer): TMunic;

procedure TMunicList.Put(Index: integer; Item: TMunic);

procedure TMunicList.ReadFromDB;

{ TRaion }

procedure TRaion.CreateMunicList;
begin
  FMunicList := TMunicList.Create;
  FMunicList.Connection := Self.Connection;
  FMunicList.Parent := Self.ID;
end;

function TRaion.GetMunicList: TMunicList;
begin
  if FMunicList.Count = 0 then
    FMunicList.ReadFromDB;
  Result := FMunicList;
end;

procedure TRaion.SetMunicList(const Value: TMunicList);
begin
  FMunicList := Value;
end;

{ TTownList }

const
  cSQL_GetTownFromParent: string =
    'SELECT id, pref, name, okato, kadastr FROM adr WHERE lvl = 3 AND' +
                                            ' parent_id = :parent_id';

//реализация методов аналогично TRaionList
function TTownList.Add(Town: TTown): integer;

function TTownList.Get(Index: integer): TTown;

procedure TTownList.Put(Index: integer; Item: TTown);

procedure TTownList.ReadFromDB;


{ TMunic }

procedure TMunic.CreateTownList;
begin
  FTownList := TTownList.Create;
  FTownList.Connection := Self.Connection;
  FTownList.Parent := Self.ID;
end;

function TMunic.GetTownList: TTownList;
begin
  if FTownList.Count = 0 then
    FTownList.ReadFromDB;
  Result := FTownList
end;

procedure TMunic.SetTownList(const Value: TTownList);
begin
  FTownList := Value;
end;

{ TStreet }

procedure TStreet.SetDocument(const Value: string);
begin
  FDocument := Value;
end;

procedure TStreet.SetPrefix(const Value: string);
begin
  FPrefix := Value;
end;

{ TStreetList }

const
  cSQL_GetStreetFromParent: string =
    'SELECT adr.id, pref, adr.name, doc.name ' +
    'FROM adr INNER JOIN doc ON doc.id = adr.id_doc ' +
    'WHERE lvl = 4 AND parent_id = :parent_id';

//реализация методов аналогично TRaionList
function TStreetList.Add(Street: TStreet): integer;

function TStreetList.Get(Index: integer): TStreet;

procedure TStreetList.Put(Index: integer; Item: TStreet);

procedure TStreetList.ReadFromDB;


{ TTown }

procedure TTown.CreateStreetList;
begin
  FStreetList := TStreetList.Create;
  FStreetList.Connection := Self.Connection;
  FStreetList.Parent := Self.ID;

end;

function TTown.GetStreetList: TStreetList;
begin
  if FStreetList.Count = 0 then
    FStreetList.ReadFromDB;
  Result := FStreetList
end;

procedure TTown.SetPrefix(const Value: string);
begin
  FPrefix := Value;
end;

procedure TTown.SetStreetList(const Value: TStreetList);
begin
  FStreetList := Value;
end;

end.
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 21:56.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter