mirror of
https://github.com/danieleteti/delphimvcframework.git
synced 2024-11-16 16:25:54 +01:00
221 lines
6.0 KiB
ObjectPascal
221 lines
6.0 KiB
ObjectPascal
// ***************************************************************************
|
|
//
|
|
// Delphi MVC Framework
|
|
//
|
|
// Copyright (c) 2010-2021 Daniele Teti and the DMVCFramework Team
|
|
//
|
|
// https://github.com/danieleteti/delphimvcframework
|
|
//
|
|
// ***************************************************************************
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
// *************************************************************************** }
|
|
|
|
unit MVCFramework.FireDAC.Utils;
|
|
|
|
{$I dmvcframework.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
FireDAC.Comp.Client, FireDAC.Stan.Param, System.Rtti, JsonDataObjects;
|
|
|
|
type
|
|
TFireDACUtils = class sealed
|
|
private
|
|
class var CTX: TRttiContext;
|
|
class function InternalExecuteQuery(AQuery: TFDQuery; AObject: TObject;
|
|
WithResult: boolean): Int64;
|
|
public
|
|
class constructor Create;
|
|
class destructor Destroy;
|
|
class function ExecuteQueryNoResult(AQuery: TFDQuery;
|
|
AObject: TObject): Int64;
|
|
class procedure ExecuteQuery(AQuery: TFDQuery; AObject: TObject);
|
|
class procedure ObjectToParameters(AFDParams: TFDParams; AObject: TObject; AParamPrefix: string = '';
|
|
ASetParamTypes: boolean = True);
|
|
class procedure CreateDatasetFromMetadata(AFDMemTable: TFDMemTable; AMeta: TJSONObject);
|
|
end;
|
|
|
|
implementation
|
|
|
|
uses
|
|
System.Generics.Collections,
|
|
Data.DB,
|
|
System.Classes,
|
|
MVCFramework.Serializer.Commons,
|
|
System.SysUtils;
|
|
|
|
{ TFireDACUtils }
|
|
|
|
class constructor TFireDACUtils.Create;
|
|
begin
|
|
TFireDACUtils.CTX := TRttiContext.Create;
|
|
end;
|
|
|
|
class procedure TFireDACUtils.CreateDatasetFromMetadata(
|
|
AFDMemTable: TFDMemTable; AMeta: TJSONObject);
|
|
var
|
|
lJArr: TJSONArray;
|
|
I: Integer;
|
|
lJObj: TJSONObject;
|
|
begin
|
|
if AMeta.IsNull('fielddefs') then
|
|
begin
|
|
raise EMVCDeserializationException.Create('Invalid Metadata objects. Property [fielddefs] required.');
|
|
end;
|
|
|
|
AFDMemTable.Active := False;;
|
|
AFDMemTable.FieldDefs.Clear;
|
|
lJArr := AMeta.A['fielddefs'];
|
|
for I := 0 to lJArr.Count - 1 do
|
|
begin
|
|
lJObj := lJArr.Items[I].ObjectValue;
|
|
AFDMemTable.FieldDefs.Add(
|
|
lJObj.S['fieldname'],
|
|
TFieldType(lJObj.I['datatype']),
|
|
lJObj.I['size']);
|
|
{ TODO -oDanieleT -cGeneral : Why don't change the display name? }
|
|
AFDMemTable.FieldDefs[I].DisplayName := lJObj.S['displayname'];
|
|
end;
|
|
AFDMemTable.CreateDataset;
|
|
end;
|
|
|
|
class destructor TFireDACUtils.Destroy;
|
|
begin
|
|
TFireDACUtils.CTX.Free;
|
|
end;
|
|
|
|
class procedure TFireDACUtils.ExecuteQuery(AQuery: TFDQuery; AObject: TObject);
|
|
begin
|
|
InternalExecuteQuery(AQuery, AObject, True);
|
|
end;
|
|
|
|
class function TFireDACUtils.ExecuteQueryNoResult(AQuery: TFDQuery;
|
|
AObject: TObject): Int64;
|
|
begin
|
|
Result := InternalExecuteQuery(AQuery, AObject, False);
|
|
end;
|
|
|
|
class procedure TFireDACUtils.ObjectToParameters(AFDParams: TFDParams;
|
|
AObject: TObject; AParamPrefix: string; ASetParamTypes: boolean);
|
|
var
|
|
I: Integer;
|
|
pname: string;
|
|
_rttiType: TRttiType;
|
|
obj_fields: TArray<TRttiProperty>;
|
|
obj_field: TRttiProperty;
|
|
obj_field_attr: MVCColumnAttribute;
|
|
Map: TObjectDictionary<string, TRttiProperty>;
|
|
f: TRttiProperty;
|
|
fv: TValue;
|
|
PrefixLength: Integer;
|
|
|
|
function KindToFieldType(AKind: TTypeKind; AProp: TRttiProperty): TFieldType;
|
|
begin
|
|
case AKind of
|
|
tkInteger:
|
|
Result := ftInteger;
|
|
tkFloat:
|
|
begin // daniele teti 2014-05-23
|
|
if AProp.PropertyType.QualifiedName = 'System.TDate' then
|
|
Result := ftDate
|
|
else if AProp.PropertyType.QualifiedName = 'System.TDateTime' then
|
|
Result := ftDateTime
|
|
else if AProp.PropertyType.QualifiedName = 'System.TTime' then
|
|
Result := ftTime
|
|
else
|
|
Result := ftFloat;
|
|
end;
|
|
tkChar, tkString:
|
|
Result := ftString;
|
|
tkWChar, tkUString, tkLString, tkWString:
|
|
Result := ftWideString;
|
|
tkVariant:
|
|
Result := ftVariant;
|
|
tkArray:
|
|
Result := ftArray;
|
|
tkInterface:
|
|
Result := ftInterface;
|
|
tkInt64:
|
|
Result := ftLongWord;
|
|
else
|
|
Result := ftUnknown;
|
|
end;
|
|
end;
|
|
|
|
begin
|
|
PrefixLength := Length(AParamPrefix);
|
|
Map := TObjectDictionary<string, TRttiProperty>.Create;
|
|
try
|
|
if Assigned(AObject) then
|
|
begin
|
|
_rttiType := CTX.GetType(AObject.ClassType);
|
|
obj_fields := _rttiType.GetProperties;
|
|
for obj_field in obj_fields do
|
|
begin
|
|
if TMVCSerializerHelper.HasAttribute<MVCColumnAttribute>(obj_field, obj_field_attr) then
|
|
begin
|
|
Map.Add(MVCColumnAttribute(obj_field_attr).FieldName.ToLower,
|
|
obj_field);
|
|
end
|
|
else
|
|
begin
|
|
Map.Add(obj_field.Name.ToLower, obj_field);
|
|
end
|
|
end;
|
|
end;
|
|
for I := 0 to AFDParams.Count - 1 do
|
|
begin
|
|
pname := AFDParams[I].Name.ToLower;
|
|
if pname.StartsWith(AParamPrefix, True) then
|
|
Delete(pname, 1, PrefixLength);
|
|
if Map.TryGetValue(pname, f) then
|
|
begin
|
|
fv := f.GetValue(AObject);
|
|
// #001: Erro ao definir parametros
|
|
if ASetParamTypes then
|
|
begin
|
|
AFDParams[I].DataType := KindToFieldType(fv.Kind, f);
|
|
end;
|
|
// #001: FIM
|
|
// DmitryG - 2014-03-28
|
|
AFDParams[I].Value := fv.AsVariant;
|
|
end
|
|
else
|
|
begin
|
|
AFDParams[I].Clear;
|
|
end;
|
|
end;
|
|
finally
|
|
Map.Free;
|
|
end
|
|
end;
|
|
|
|
class function TFireDACUtils.InternalExecuteQuery(AQuery: TFDQuery; AObject: TObject;
|
|
WithResult: boolean): Int64;
|
|
begin
|
|
ObjectToParameters(AQuery.Params, AObject);
|
|
Result := 0;
|
|
if WithResult then
|
|
AQuery.Open
|
|
else
|
|
begin
|
|
AQuery.ExecSQL;
|
|
Result := AQuery.RowsAffected;
|
|
end;
|
|
end;
|
|
|
|
end.
|