Ver Mensaje Individual
  #4  
Antiguo 17-02-2009
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Reputación: 30
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
¡Hola!

Cuando se trata de campos, las propiedades AsXXX ofrecen una manera muy eficaz de leer y asignar valores. Pero existe algo de considerar en las propiedades AsXXX de los parámetros, que explico en seguida.

Hace varios días, durante una asesoría a un colega, encontramos que había problemas con el método AsString de un parámetro al usar una sintaxis como:
Código Delphi [-]
ParamByName ('CampoNumerico').AsString := Edit1.Text;
Resulta que la base de datos era Paradox vía BDE, y al tratar de ejecutar la sentencia SQL el servidor la rechazaba por un problema de tipos. El campo era flotante, y, sólo por intentar algo diferente, sugerí cambiar la sentencia por:
Código Delphi [-]
ParamByName ('CampoNumerico').AsFloat := StrToFloat (Edit1.Text);
Y entonces funcionó.

En ese momento adjudiqué el problema por completo a la BDE. Pero leyendo ahora este hilo me entró la sospecha de algo relacionado a la propiedad DataType de los parámetros, y dicha sospecha se ha confirmado. Resulta que los métodos SetAsXXX de TParam, que son las rutinas de escritura de sus propiedades AsXXX, ¡cambian el valor de DataType en función de la propiedad usada para la asignación!

Código Delphi [-]
...
procedure TParam.SetAsBoolean(Value: Boolean);
begin
  FDataType := ftBoolean;
  Self.Value := Value;
end;

procedure TParam.SetAsFloat(const Value: Double);
begin
  FDataType := ftFloat;
  Self.Value := Value;
end;

procedure TParam.SetAsString(const Value: string);
begin
  if FDataType <> ftFixedChar then FDataType := ftString;
  Self.Value := Value;
end;

procedure TParam.SetAsVariant(const Value: Variant);
begin
  if ParamRef = Self then
  begin
    FBound := not VarIsClear(Value);
    FNull := VarIsClear(Value) or VarIsNull(Value);
    if FDataType = ftUnknown then
      case VarType(Value) of
        varSmallint, varShortInt, varByte: FDataType := ftSmallInt;
        varWord, varInteger: FDataType := ftInteger;
        varCurrency: FDataType := ftBCD;
        varLongWord, varSingle, varDouble: FDataType := ftFloat;
  ...
end;
...
(unidad DB.pas de Delphi 7)

Entonces eso explica, en parte, por qué la BDE / Paradox rechazaba aquella sentencia, en la que se intentaba asignar valor a un parámetro numérico con la propiedad AsString de ese TParam.

Nunca he tenido este problema con Firebird vía IBX o dbExpress (creo), así que ya había dado por hecho que estas propiedades AsXXX eran meros convertidores (como las de TField).

Pero con esto que sale a la luz, ¿deberíamos usarlas con precautoria atención ante la posibilidad de cambiar de motor? Incluso, según se ve, hasta la misma propiedad Value lo hace (SetAsVariant es su método de escritura).

¿Está mal que los métodos SetAsXXX de TParam modifiquen la propiedad DataType? Sin razonarlo mucho, pareciera que sí, pero alguna explicación deberá existir.

Por alguna razón, para la VCL los objetos TParam son de "menos valía" que los TField. De hecho hay un divertido y "criminal" mecanismo de pérdida de parámetros en la mayoría de las clases que implementan el método PSSetParams, cuando nos olvidamos de establecerlos correctamente en el lado cliente.

Creo que habría que investigar cómo trata cada tecnología (BDE, IBX, ADO, dbExpress) a los parámetros, para tener una idea clara de la seguridad que ofrecen las propiedades AsXXX y Value de TParam.

Un abrazo parametrizado.

Al González.

Última edición por Al González fecha: 17-02-2009 a las 05:01:53.
Responder Con Cita