【Delphi】Utils.ADODB

unit Utils.ADODB;
 
interface
 
uses
    System.Classes, System.TypInfo, System.Win.ComObj, Winapi.ActiveX, Data.DB, Data.Win.ADODB;
 
type
 
    {
        TMPropList class type
    }
 
    TMPropList = class(TObject)
    private
        FPropCount: Integer;
        FPropList: PPropList;
    protected
        function GetPropName(x: Integer): ShortString;
        function GetProp(x: Integer): PPropInfo;
    public
        constructor Create(aObj: TPersistent);
        destructor Destroy; override;
        property PropCount: Integer read FPropCount;
        property PropNames[x: Integer]: ShortString read GetPropName;
        property Props[x: Integer]: PPropInfo read GetProp;
    end;
 
////////////////////////////////////////////////////////////////////////////////
 
    {
        TDbSetProxy class type
    }
 
    TDbSetProxy = class(TPersistent)
    private
        FDataSet: TDataSet;
        FPropList: TMPropList;
        FIsLoop: Boolean;
    protected
        procedure BeginEdit;
        procedure EndEdit;
        function GetInteger(x: Integer): Integer; virtual;
        function GetFloat(x: Integer): Double; virtual;
        function GetString(x: Integer): string; virtual;
        function GetVariant(x: Integer): Variant; virtual;
        procedure SetInteger(x: Integer; aValue: Integer); virtual;
        procedure SetFloat(x: Integer; aValue: Double); virtual;
        procedure SetString(x: Integer; aValue: string); virtual;
        procedure SetVariant(x: Integer; aValue: Variant); virtual;
    public
        constructor Create(ds: TDataSet);
        destructor Destroy; override;
        procedure AfterConstruction; override;
        function HasNext: Boolean;
        function RecordCount: Integer;
        property DataSet: TDataSet read FDataSet;
    end;
 
////////////////////////////////////////////////////////////////////////////////
 
    {
        TDbParameter class type
    }
 
    TDbParameter = class(TObject)
    private
        thisKey: string;
        thisValue: Variant;
        thisDataType: TDataType;
        thisSize: Integer;
    public
        constructor Create(key: string; value: Variant); overload;
        constructor Create(key: string; value: Variant; dataType: TFieldType; size: Integer); overload;
        function GetKey: string;
        procedure SetKey(key: string);
        function GetValue: Variant;
        procedure SetValue(value: Variant);
        function GetDataType: TDataType;
        procedure SetDataType(dataType: TDataType);
        function GetSize: Integer;
        procedure SetSize(size: Integer);
    published
        property key: string read GetKey write SetKey;
        property value: Variant read GetValue write SetValue;
        property dataType: TDataType read GetDataType write SetDataType;
        property size: Integer read GetSize write SetSize;
    end;
 
////////////////////////////////////////////////////////////////////////////////
 
    {
        TDbOperation class type
    }
 
    TDbOperation = class(TObject)
    private
        { 连接字符串 }
        thisConnectionString: string;
        { 关闭Command }
        procedure CloseCommand(cmd: TADOCommand);
    public
        { ctor }
        constructor Create(connstr: string); overload;
        { 获取一个连接 }
        function GetConnection(): TADOConnection;
        { 执行单条CUD }
        function ExecSQL(sql: string): Boolean; overload;
        { 执行单条CUD, 参数化 }
        function ExecSQL(sql: string; parms: array of TDbParameter): Boolean; overload;
        { 批量执行CUD }
        function BatchExecSQL(sqls: array of string): Boolean;
        { 获取单个值的R }
        function GetSingle(sql: string): Variant; overload;
        { 获取单个值的R,  参数化 }
        function GetSingle(sql: string; parms: array of TDbParameter): Variant; overload;
        { 获取一个Query对象 }
        function GetQuery(sql: string): TADOQuery; overload;
        { 获取一个Query对象, 参数化 }
        function GetQuery(sql: string; parms: array of TDbParameter): TADOQuery; overload;
        { 关闭Query }
        procedure CloseQuery(query: TADOQuery);
        { 关闭连接 }
        procedure CloseConnection(connection: TADOConnection);
        { 关闭Query及连接 }
        procedure Close(query: TADOQuery; connection: TADOConnection);
    end;
 
implementation
 
 
{
    TMPropList Class implementation
}
 
constructor TMPropList.Create(aObj: TPersistent);
begin
    FPropCount := GetTypeData(aObj.ClassInfo)^.PropCount;
    FPropList := Nil;
    if FPropCount > 0 then begin
        GetMem(FPropList, FPropCount * SizeOf(Pointer));
        GetPropInfos(aObj.ClassInfo, FPropList);
    end;
end;
 
destructor TMPropList.Destroy;
begin
    if Assigned(FPropList) then
        FreeMem(FPropList);
    inherited;
end;
 
function TMPropList.GetProp(x: Integer): PPropInfo;
begin
    Result := Nil;
    if (Assigned(FPropList)) then
        Result := FPropList[x];
end;
 
function TMPropList.GetPropName(x: Integer): ShortString;
begin
    Result := GetProp(x)^.Name;
end;
 
 
////////////////////////////////////////////////////////////////////////////////
 
{
    TDbSetProxy Class implementation
}
 
constructor TDbSetProxy.Create(ds: TDataSet);
begin
    inherited Create;
    FDataSet := ds;
    FDataSet.Open;
    FIsLoop := false;
end;
 
destructor TDbSetProxy.Destroy;
var
    conn: TADOConnection;
begin
    FPropList.Free;
    if Assigned(FDataSet) then begin
        if FDataSet is TADOQuery then begin
            conn := TADOQuery(FDataSet).connection;
            conn.Close;
            conn.Free;
            conn := nil;
        end;
        FDataSet.Close;
        FDataSet.Free;
        FDataSet := nil;
    end;
    inherited;
end;
 
procedure TDbSetProxy.AfterConstruction;
begin
    inherited;
    FPropList := TMPropList.Create(Self);
end;
 
procedure TDbSetProxy.BeginEdit;
begin
    if (FDataSet.State <> dsEdit) and (FDataSet.State <> dsInsert) then
        FDataSet.Edit;
end;
 
procedure TDbSetProxy.EndEdit;
begin
    if (FDataSet.State = dsEdit) or (FDataSet.State = dsInsert) then
        FDataSet.Post;
end;
 
function TDbSetProxy.GetInteger(x: Integer): Integer;
begin
    Result := FDataSet.FieldByName(FPropList.PropNames[x]).AsInteger;
end;
 
function TDbSetProxy.GetFloat(x: Integer): Double;
begin
    Result := FDataSet.FieldByName(FPropList.PropNames[x]).AsFloat;
end;
 
function TDbSetProxy.GetString(x: Integer): string;
begin
    Result := FDataSet.FieldByName(FPropList.PropNames[x]).AsString;
end;
 
function TDbSetProxy.GetVariant(x: Integer): Variant;
begin
    Result := FDataSet.FieldByName(FPropList.PropNames[x]).value;
end;
 
procedure TDbSetProxy.SetInteger(x, aValue: Integer);
begin
    BeginEdit;
    FDataSet.FieldByName(FPropList.PropNames[x]).AsInteger := aValue;
end;
 
procedure TDbSetProxy.SetFloat(x: Integer; aValue: Double);
begin
    BeginEdit;
    FDataSet.FieldByName(FPropList.PropNames[x]).AsFloat := aValue;
end;
 
procedure TDbSetProxy.SetString(x: Integer; aValue: string);
begin
    BeginEdit;
    FDataSet.FieldByName(FPropList.PropNames[x]).AsString := aValue;
end;
 
procedure TDbSetProxy.SetVariant(x: Integer; aValue: Variant);
begin
    BeginEdit;
    FDataSet.FieldByName(FPropList.PropNames[x]).value := aValue;
end;
 
function TDbSetProxy.HasNext: Boolean;
begin
    Result := not FDataSet.Eof;
    if FIsLoop then begin
        EndEdit;
        FDataSet.Next;
        Result := not FDataSet.Eof;
        if not Result then begin
            FDataSet.First;
            FIsLoop := false;
        end;
    end
    else if Result then begin
        FIsLoop := true;
    end;
end;
 
function TDbSetProxy.RecordCount: Integer;
begin
    Result := FDataSet.RecordCount;
end;
 
 
////////////////////////////////////////////////////////////////////////////////
 
{
    TDbParameter Class implementation
}
 
function TDbParameter.GetKey;
begin
    Result := thisKey;
end;
 
procedure TDbParameter.SetKey(key: string);
begin
    thisKey := key;
end;
 
function TDbParameter.GetValue;
begin
    Result := thisValue;
end;
 
procedure TDbParameter.SetValue(value: Variant);
begin
    thisValue := value;
end;
 
function TDbParameter.GetDataType;
begin
    Result := thisDataType;
end;
 
procedure TDbParameter.SetDataType(dataType: TFieldType);
begin
    thisDataType := dataType;
end;
 
function TDbParameter.GetSize;
begin
    Result := thisSize;
end;
 
procedure TDbParameter.SetSize(size: Integer);
begin
    thisSize := size;
end;
 
constructor TDbParameter.Create(key: string; value: Variant);
begin
    thisKey := key;
    thisValue := value;
    thisDataType := ftUnknown;
    thisSize := -1;
end;
 
constructor TDbParameter.Create(key: string; value: Variant; dataType: TFieldType; size: Integer);
begin
    thisKey := key;
    thisValue := value;
    thisDataType := dataType;
    thisSize := size;
end;


////////////////////////////////////////////////////////////////////////////////
 
{
    TDbOperation Class implementation
}
 
{ 获取一个连接 }
function TDbOperation.GetConnection: TADOConnection;
var
    conn: TADOConnection;
begin
    conn := TADOConnection.Create(nil);
    conn.ConnectionString := thisConnectionString;
    conn.LoginPrompt := False;
    conn.Open;
    Result := conn;
end;
 
{ 执行单条CUD }
function TDbOperation.ExecSQL(sql: string): Boolean;
var
    args: array of TDbParameter;
begin
    args := nil;
    Result := ExecSQL(sql, args);
end;
 
{ 执行单条CUD, 参数化 }
function TDbOperation.ExecSQL(sql: string; parms: array of TDbParameter): Boolean;
var
    command: TADOCommand;
    conn: TADOConnection;
    parm: TDbParameter;
    i: Integer;
begin
    try
        conn := GetConnection;
        command := TADOCommand.Create(nil);
        with command do begin
            Connection := conn;
            CommandText := sql;
            for i := Low(parms) to High(parms) do begin
                parm := parms[i];
                Parameters.ParamByName(parm.key).value := parm.value;
                if (parm.dataType <> ftUnknown) then begin
                    Parameters.ParamByName(parm.key).dataType := parm.dataType;
                end;
                if (parm.size <> -1) then begin
                    Parameters.ParamByName(parm.key).size := parm.size;
                end;
            end;
            Execute;
            Result := True;
        end;
    finally
        CloseCommand(command);
        CloseConnection(conn);
    end;
end;
 
{ 批量执行CUD }
function TDbOperation.BatchExecSQL(sqls: array of string): Boolean;
var
    conn: TADOConnection;
    command: TADOCommand;
    sql: string;
    i: Integer;
begin
    try
        conn := GetConnection;
        command := TADOCommand.Create(nil);
        conn.BeginTrans;
        try
            with command do begin
                Connection := conn;
                for i := Low(sqls) to High(sqls) do begin
                    sql := sqls[i];
                    if sql <> '' then begin
                        CommandText := sql;
                        Execute;
                    end;
                end;
            end;
            conn.CommitTrans;
            Result := True;
        except
            on ex: EOleException do begin
                conn.RollbackTrans;
                Result := False;
            end;
        end;
    finally
        CloseCommand(command);
        CloseConnection(conn);
    end;
end;
 
{ 获取单个值的R }
function TDbOperation.GetSingle(sql: string): Variant;
var
    args: array of TDbParameter;
begin
    args := nil;
    Result := GetSingle(sql, args);
end;
 
{ 获取单个值的R, 参数化 }
function TDbOperation.GetSingle(sql: string; parms: array of TDbParameter): Variant;
var
    query: TADOQuery;
    conn: TADOConnection;
begin
    try
        conn := GetConnection;
        query := GetQuery(sql, parms);
        if query.RecordCount < 0 then begin
            Result := '';
        end;
        query.First;
        Result := query.Fields.Fields[0].AsVariant;
    finally
        Close(query, conn);
    end;
end;
 
{ 获取一个Query对象 }
function TDbOperation.GetQuery(sql: string): TADOQuery;
var
    args: array of TDbParameter;
begin
    args := nil;
    Result := GetQuery(sql, args);
end;
 
{ 获取一个Query对象, 参数化 }
function TDbOperation.GetQuery(sql: string; parms: array of TDbParameter): TADOQuery;
var
    query: TADOQuery;
    parm: TDbParameter;
    i: Integer;
begin
    query := TADOQuery.Create(nil);
    query.Connection := GetConnection;
    query.SQL.Add(sql);
    for i := Low(parms) to High(parms) do begin
        parm := parms[i];
        query.Parameters.ParamByName(parm.key).value := parm.value;
        if (parm.dataType <> ftUnknown) then begin
            query.Parameters.ParamByName(parm.key).dataType := parm.dataType;
        end;
        if (parm.size <> -1) then begin
            query.Parameters.ParamByName(parm.key).size := parm.size;
        end;
    end;
    query.Open;
    Result := query;
end;
 
{ 关闭Query }
procedure TDbOperation.CloseQuery(query: TADOQuery);
begin
    if Assigned(query) then begin
        query.Close;
        query.Free;
        query := nil;
    end;
end;
 
{ 关闭连接 }
procedure TDbOperation.CloseConnection(connection: TADOConnection);
begin
    if Assigned(connection) then begin
        connection.Close;
        connection.Free;
        connection := nil;
    end;
end;
 
{ 关闭Query及连接 }
procedure TDbOperation.Close(query: TADOQuery; connection: TADOConnection);
begin
    CloseQuery(query);
    CloseConnection(connection);
end;
 
{ 关闭Command }
procedure TDbOperation.CloseCommand(cmd: TADOCommand);
begin
    if Assigned(cmd) then begin
        cmd.Cancel;
        cmd.Free;
        cmd := nil;
    end;
end;
 
{ ctor }
constructor TDbOperation.Create(connstr: string);
begin
    thisConnectionString := connstr;
end;
 
////////////////////////////////////////////////////////////////////////////////
 
initialization
    CoInitialize(nil);
 
finalization
    CoUnInitialize;
 
end.

原文地址:https://www.cnblogs.com/zhuzhongxing/p/14147081.html