Идея стандартизации элементов клиента базы данных

Previous  Top  Next

    
 

 

Code:

{ **** UBPFD *********** by delphibase.endimus.com ****

>> Идея стандартизации элементов клиента базы данных.

 

Компонент доступа к данным,потомок TADOStoredProc.

Предназначен для написания клиента для MS SQL Server 2000 (можно использовать и

для более ранних версий, но придется поработать над шаблоном хранимой

процедуры).

Позволяет управлять операциями добавления, редактирования и

удаления (и некоторыми другими)на клиенте со стороны сервера однообразно для

всех данных. Тем самым достигается некоторая стандартизация клиента и при

изменении серверной части не придется изменять клиента(конечно же в разумных

пределах).

Для большей красоты не помешает создать некоторые другие прибамбасы, например,

форму, исходную для всех форм проекта.

Но это уже не относится к данному разделу.

 

Зависимости: Windows, Messages, SysUtils, Classes, DB, ADODB

Автор:       Пенов Сергей, spenov@narod.ru, ICQ:122597033, Москва

Copyright:   Пенов Сергей

Дата:        07 мая 2002 г.

***************************************************** }

 

//Шаблон хранимой процедуры

{

CREATE PROCEDURE [upTemplateProcedure]

  @KeyValue INT = NULL -- требуется для обновления измененной записи в клиенте.

AS

-- Data (Требуемая информация)

SELECT ColumnList

FROM TheTable

WHERE @KeyValue IS NULL OR TheKey=@KeyValue -- возвращаем либо все(операция

открытия), либо конкретную запись (операция обновления)

 

IF @KeyValue IS NULL BEGIN -- если операция открытия, то возвращаем необходимую

дополнительную информацию для настройки клиента

  -- Properties -- динамические свойства TADOStoredProc, список формируется

таким образом. В большинстве случаев изменять его не приходится.

  SELECT 'Property'='Unique Table' , 'Value'='TheTable' UNION

  SELECT 'Property'='Resync Command' , 'Value'='EXEC upTemplateProcedure ?' --

!!! команда обновления измененной записи !!!

  -- Table Operations

     -- Здесь формируется набор данных, возвращающий какие операции может

совершать текущий пользователь с этими данными. Это, естественно, простейший

пример и возможно под конкретную ситуацию его надо будет изменить (запрос)

  SELECT DISTINCT PRIVILEGE_TYPE AS [Operation], 1 AS [Value] -- 1 - можно, 0

(или нет записи) - нельзя. Operation = INSERT,UPDATE,DELETE

    FROM INFORMATION_SCHEMA.TABLE_PRIVILEGES

    WHERE TABLE_NAME = 'TheTable'

  -- Columns Operations -- возможность редактирования столбцов пользователем

  SELECT DISTINCT COLUMN_NAME AS [Column], 0 AS [ReadOnly] 0 - может

редактировать, 1 ( или нет записи) - не может.

    FROM INFORMATION_SCHEMA.COLUMN_PRIVILEGES

    WHERE TABLE_NAME = 'TheTable'

      AND PRIVILEGE_TYPE = 'UPDATE'

 

  -- Далее можно добавлять свои дополнительные данные для более детальной

настройки клиета. В клиенте к ним доступ через свойство

TADOApostrofStoredProc .Recordsets.

 

END

}

 

unit Un_TApostrofStoredProc;

 

interface

 

uses

Windows, Messages, SysUtils, Classes, DB, ADODB;

 

type

TADOApostrofStoredProc = class(TADOStoredProc)

private

   FCanINSERT: Boolean;

   FCanUPDATE: Boolean;

   FCanDELETE: Boolean;

   FRecordsets: TInterfaceList;

   FOpenTime: TDateTime;

   function GetRecordset(I: Integer): _Recordset;

   function GetRecordsetCount: Integer;

protected

   procedure DoBeforeOpen; override;

   procedure DoBeforeClose; override;

   procedure DoAfterOpen; override;

   procedure OpenCursor(InfoQuery: Boolean = False); override;

   procedure SetFieldData(Field: TField; Buffer: Pointer; NativeFormat:

     Boolean); override;

public

   constructor Create(AOwner: TComponent); override;

   property CanINSERT: Boolean read FCanINSERT;

   property CanUPDATE: Boolean read FCanUPDATE;

   property CanDELETE: Boolean read FCanDELETE;

   property Recordsets[I: Integer]: _Recordset read

   GetRecordset; //Дополнительные наборы данных, возвращенные хранимой процедурой

   property RecordsetCount: Integer read GetRecordsetCount;

   property OpenTime: TDateTime read FOpenTime write FOpenTime; //Время

   открытия процедуры.

end;

 

procedure Register;

 

implementation

 

uses

ADOint, DBConsts;

 

procedure Register;

begin

RegisterComponents('ADOApostrof', [TADOApostrofStoredProc]);

end;

 

function TADOApostrofStoredProc.GetRecordset(I: Integer): _Recordset;

begin

Result := _Recordset(FRecordsets[I]);

end;

 

function TADOApostrofStoredProc.GetRecordsetCount: Integer;

begin

Result := FRecordsets.Count;

end;

 

constructor TADOApostrofStoredProc.Create(AOwner: TComponent);

begin

inherited;

FRecordsets := TInterfaceList.Create;

end;

 

procedure TADOApostrofStoredProc.DoBeforeOpen;

begin

FCanINSERT := False;

FCanUPDATE := False;

FCanDELETE := False;

inherited;

end;

 

procedure TADOApostrofStoredProc.DoBeforeClose;

begin

inherited;

FRecordsets.Clear;

end;

 

procedure TADOApostrofStoredProc.DoAfterOpen;

var

R: _Recordset;

RecordsAffected, I: Integer;

begin

//Все столбцы в ReadOnly!

for I := 0 to Fields.Count - 1 do

   Fields[I].ReadOnly := True;

//Установка некоторых свойств

Properties['Update Criteria'].Value := adCriteriaKey;

Properties['Update Resync'].Value := adResyncAll;

//Свойства из базы

R := NextRecordset(RecordsAffected);

while Assigned(R) do

begin

   FRecordsets.Add(R);

   if (R.Fields.Count = 2) and (UpperCase(R.Fields[0].Name) = 'PROPERTY') and

     (UpperCase(R.Fields[1].Name) = 'VALUE') then

   begin //Properties

     if R.RecordCount > 0 then

     begin

       R.MoveFirst;

       while not R.EOF do

       begin

         Properties[R.Fields[0].Value].Value := R.Fields[1].Value;

         R.MoveNext;

       end;

     end;

   end

   else if (R.Fields.Count = 2) and (UpperCase(R.Fields[0].Name) = 'OPERATION')

     and (UpperCase(R.Fields[1].Name) = 'VALUE') then

   begin //Операции над таблицей

     if R.RecordCount > 0 then

     begin

       R.MoveFirst;

       while not R.EOF do

       begin

         if R.Fields[0].Value = 'INSERT' then

           FCanINSERT := (R.Fields[1].Value = 1)

         else if R.Fields[0].Value = 'UPDATE' then

           FCanUPDATE := (R.Fields[1].Value = 1)

         else if R.Fields[0].Value = 'DELETE' then

           FCanDELETE := (R.Fields[1].Value = 1);

         R.MoveNext;

       end;

     end;

   end

   else if (R.Fields.Count = 2) and (UpperCase(R.Fields[0].Name) = 'COLUMN')

     and (UpperCase(R.Fields[1].Name) = 'READONLY') then

   begin //Операции над столбцами

     if R.RecordCount > 0 then

     begin

       R.MoveFirst;

       while not R.EOF do

       begin

         if Assigned(FindField(R.Fields[0].Value)) then

           FieldByName(R.Fields[0].Value).ReadOnly := (R.Fields

             [1].Value = 1);

         R.MoveNext;

       end;

     end;

   end;

   R := NextRecordset(RecordsAffected);

end;

inherited;

end;

 

procedure TADOApostrofStoredProc.SetFieldData(Field: TField; Buffer: Pointer;

NativeFormat: Boolean);

var

Buf: Boolean;

begin

Buf := Field.ReadOnly;

Field.ReadOnly := Field.ReadOnly and (State <> dsInsert);

try

   inherited;

finally

   Field.ReadOnly := Buf;

end;

end;

 

procedure TADOApostrofStoredProc.OpenCursor(InfoQuery: Boolean);

var

TheTime: TDateTime;

begin

TheTime := Time;

inherited;

FOpenTime := Time - TheTime;

end;

 

end.

 

©Drkb::02873