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

{codecitation class=»brush: pascal; gutter: false;» width=»600px»}

Автор: Пенов Сергей

WEB-сайт: http://delphibase.endimus.com

{ **** 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.

{/codecitation}

Добавить комментарий