2010-09-17 27 views
7

Existe-t-il un moyen standard de convertir les valeurs TVarRec et Variant?Comment faire pour convertir entre TVarRec et Variant?

Je veux analyser un 'tableau de const' et utiliser les valeurs pour remplir les paramètres dans un TMSQuery. Pour ce faire, j'utilise une liste de noms de colonnes (générés à partir de TMSQuery.KeyFields), et en faisant correspondre les valeurs du tableau avec les noms de colonnes dans KeyFields (par position), puis en utilisant le nom de la colonne pour paramétrer ParamByName .

Le code ci-dessous est ce que j'ai trouvé, mais VarRecToVariant ne semble pas très élégant. Y a-t-il une meilleure solution?

keyFields: TStringList; 
    // List of table column names (keyFields.DelimitedText := query.KeyFields;) 
    // e.g. Name, Age 
    query: TMSQuery; 
    // Parametrized query with a parameter for each field in keyFields 
    // SELECT * FROM People WHERE Age=:Age AND Name=:Name 

    // If keyValues is ['Bob', 42] the resulting query should be 
    // SELECT * FROM People WHERE Age=42 AND Name='Bob' 

    procedure Read(keyValues: array of const); 
    var 
    i: Integer; 
    name: string; 
    value: Variant; 
    begin 
    ... 
    for i := 0 to keyFields.Count - 1 do 
    begin 
     name := keyFields[i]; 
     value := VarRecToVariant(keyValues[i]); 
     query.ParamByName(name).Value := value; 
    end; 
    query.Open 
    ... 
    end; 

    function VarRecToVariant(varRec: TVarRec): Variant; 
    begin 
    case varRec.VType of 
     vtInteger: result := varRec.VInteger; 
     vtBoolean: result := varRec.VBoolean; 
     vtChar:  result := varRec.VChar; 
     vtExtended: result := varRec.VExtended^; 
     vtString:  result := varRec.VString^; 
     ... 
    end; 
    end; 

Remarques:

  • Les valeurs dans le tableau de const dépendent des paramètres de la requête. L'appelant sait ce que c'est, mais la méthode qui utilise le tableau ne sait pas combien ou quel type attendre. C'est à dire. Je ne peux pas changer la méthode en Read (nom: string; age: integer).
  • Les paramètres ne sont pas nécessairement utilisés dans le même ordre que les valeurs spécifiées dans le tableau de const. Dans l'exemple, keyFields est spécifié en tant que "Name, Age" mais la requête utilise Age before Name. Cela signifie que Params [i] .Value: = keyValues ​​[i] ne fonctionnera pas. Je pense que VarRecToVariant serait encore nécessaire de toute façon, ce que j'essaie d'éviter).
+0

Le ruban adhésif n'est jamais très joli, et c'est essentiellement ce que vous faites, en joignant deux systèmes différents. Il y aura toujours un décalage d'impédance. –

+1

BTW, il existe déjà une fonction très similaire dans la VCL: ConvertToVariant dans l'unité MxCommon. –

+0

@TOndrej, je ne connaissais pas ConvertToVariant, merci de le mentionner. – WileCau

Répondre

5

Remplacer

procedure Read(keyValues: array of const); 

avec

procedure Read(keyValues: array of Variant); 

Ensuite, vous aurez pas besoin de convertir TVarRec à la variante.

+0

merci c'est la pensée latérale dont j'avais besoin :) J'étais tellement embourbé dans les détails de la conversion du tableau que je ne pensais pas juste de changer le type de tableau. – WileCau

+2

+1 pour avoir réfléchi en dehors de la boîte. –

+0

La variante ne peut pas contenir tout ce que TVarRec peut contenir. –