FindOrCreate (CM)

De Wiki1000
function FindOrCreate(const iClassName,iWhere,iOrderBy:string,iDescendants:Boolean; iArgs:Variants; iDelegate:TitObject):TitObject;

Cette fonction recherche un objet d'une classe métier répondant à une condition.

Si l'objet n'est pas trouvé, la fonction exécute la méthode "Execute" de l'objet iDelegate dans une transaction séparée partagée, puis recherche de nouveau l'objet.

Lorsque cette méthode est utilisée dans le cadre d'une exécution parallèle, elle assure que l'objet ne sera créé qu'une fois. Ceci suppose que la transaction séparée va échouer en cas de création de doublon, il faut donc que la classe de l'objet créé comporte une règle unique adéquate.

Exclam-20px.png Attention : à l'intérieur d'une transaction longue, se comporte comme un find standard.
Result Un objet de la classe métier
iWhere Une expression objet que doit remplir l'objet.
iOrderBy Un ordre de tri appliqué dans la requête.
iDescendants Inclure les classes dérivées de la hiérarchie de classe.
iArgs Arguments de l'expression
iDelegate Objet délégation utilisé si l'objet recherché n'est pas trouvé

Le pseudo-code équivalent à cette fonction est :

function ClassManager.FindOrCreate(const iClassName:string; const iWhereFormat,iOrderBy:string; iDescendants:Boolean; const iArgs:Variant; iDelegate:TitObject):TitObject;
var rslt:boolean; new,old:TTranContext;
begin
  // Find the object
  Result := ClassManager.FindObject(iClassName,iWhereFormat,iOrderBy,iDescendants,iArgs,True);
  if Assigned(Result) then Exit;
 
  // Not found
  // Call the delegate.Execute method in a separate shared transaction
  //
  rslt := false;
  new := ClassManager.AllocTransContext;
  old := ClassManager.ActivateContext(new);
  try
    ClassManager.BeginTran;
    try
      if not _ExecuteDelegation(iDelegate,'Execute') then
       raise EScript.CreateFmt('(FindOrCreate) Delegate object %s has no Execute method',[iDelegate.Regclass.AClassName]);
      //
      rslt := ClassManager.Commit
    except
      rslt := false;
      ClassManager.RollBack;
    end;
  finally
  ClassManager.ActivateContext(old);
  end;
  //
  Result := ClassManager.FindObject(iClassName,iWhereFormat,iOrderBy,iDescendants,iArgs,True);
  if not Assigned(Result) then
   begin
     if not _ExecuteDelegation(iDelegate,'OnExecuteFailed') then
        raise ERule.CreateFmt(_TP('Impossible de créer un objet de la classe %s'),[RegClass.aClassLabel]);
   end;
end;


Info-20px.png Note : Cette fonction retourne le premier objet retrouvé.

Exemple

// delegate class
// This class create a ClassB object using unCode as parameter.
//
 MyDelegate = class
   unCode: string;
   procedure Execute;
 end;
 
procedure MyDelegate.Execute;
var instB:ClassB;
begin
  instB := ClassB.Create;
  instB.unCodeB := unCode;
end;
 
// Caller class
// This method create two objects ClassA and ClassB, ClassB is created using the delagate
//
procedure MyClass.CreateAandB(const S1,S2:string; iValue:Integer);
var instD:Delegate; instA:ClassA; instB:ClassB;
begin
  withP transaction do
   begin
     instA := ClassA.Create;
     instA.unEntierA := iValue;
     instA.unCodeA := S1;
     instA.unExtension := S1;
     //
     // Create a MyDelegate object
     instD := MyDelegate.Create;
     instD.unCode := S2;
     instB := ClassManager.FindOrCreate('ClassB','unCodeB=%1','',True,[S2],instD);
     //
     instA.refB := instB;
   end;
end;

Voir aussi :

Gestion des instances (CM)Développement DSM

Outils personnels