Skip to content

DataSnap Server Method DBXValue Parameters

This post provides more information about DataSnap server method parameters and return types. This is my second post on this subject, following DataSnap Server Method Parameters. The previous post was about "Basic" types. This post is about "Basic DBXValue" types.  The sample client and client and server projects that go with this post can be downloaded here: http://cc.embarcadero.com/item/26734

Basic Basic DBXValue Collection Connection
  • AnsiString
  • Boolean
  • Currency
  • TDateTime
  • TDBXDate
  • TDBXTime
  • Double
  • Int64
  • Integer
  • LongInt
  • OleVariant
  • Single
  • SmallInt
  • WideString
  • TDBXAnsiStringValue
  • TDBXAnsiCharsValue
  • TDBXBcdValue
  • TDBXBooleanValue
  • TDBXDateValue
  • TDBXDoubleValue
  • TDBXInt16Value
  • TDBXInt32Value
  • TDBXInt64Value
  • TDBXSingleValue
  • TDBXStringValue
  • TDBXTimeStampValue
  • TDBXTimeValue
  • TDBXWideCharsValue
  • TDBXWideStringValue
  • TDBXReader
  • TDataSet
  • TParams
  • TStream
Collection DBXValue
  • TDBXReaderValue
  • TDBXStreamValue
  • TDBXConnection
Connection DBXValue
  • TDBXConnectionValue

The following table summarizes differences between "Basic" and "Basic DBXValue" types:

  Supports null values Declaration Accessing Values Proxy generator
Default parameter direction Other parameter directions function result type Get Set
Basic No

in

in/out: use var keyword
out: use out keyword

Yes

lhs := AParameter AParameter := rhs

Yes

DBXValue

Yes

in/out

None

No

AParameter.IsNull
lhs:=AParameter.GetInt32,
lhs:=AParameter.GetString, etc.
AParameter.SetNull
AParameter.SetInt32(rhs),
AParameter.SetString(rhs), etc.

No

 

Supports null values

Support for null values is needed, for example, when a server method needs to pass values that come from a database column that allows NULL.    All DBXValue types have an IsNull property and a SetNull method.

Declaration

The var and out keywords can’t be used to specify the parameter direction of a DBXValue parameter.  The direction is always in/out.   A DBXValue type can’t be used as a function result.

Proxy Generator

The RAD Studio 2007 client proxy generator does not work properly for server methods with DBXValue parameters.  So you will need to hand code.   The sample client has code like this to call a server method:

// Non-generic version of TestSetNull
procedure TCallTestMethods.TestSetNullInt32(AConnection: TDBXConnection; I: Int32);
const
  LMethodName = 'TTestDBXInt32Value.SetNull';
var
  LIsNull: Boolean;
  LDBXCommand: TDBXCommand;
begin
  LDBXCommand := AConnection.CreateCommand;
  try
    try
      LDBXCommand.CommandType := TDBXCommandTypes.DSServerMethod;
      LDBXCommand.Text := LMethodName;
      LDBXCommand.Prepare;
      LDBXCommand.Parameters[0].Value.SetInt32(I);
      LDBXCommand.ExecuteUpdate;
      LIsNull := LDBXCommand.Parameters[0].Value.IsNull;
      LogTestResult(LMethodName, LIsNull);
    except
      on E: Exception do
      LogTestException(LMethodName, E);
    end;
  finally
    LDBXCommand.Free;
  end;
end;

Calling a server method with a TDBXInt32Value parameter is the same as calling a server method with an Int32 parameter, except that you can use SetNull and IsNull methods to work with null values.  

Accessing Values

The following table shows the methods that are used to access a non-null value from the different DBXValue types   A mismatched call, such as GetBcd on TDBXStringValue, will raise an exception. 

Get method Set method Type Use with
GetAnsiString SetAnsiString AnsiString TDBXAnsiCharsValue, TDBXAnsiStringValue
GetBcd SetBcd TBcd TDBXBcdValue
GetBoolean SetBoolean Boolean TDBXBooleanValue
GetDate SetDate TDBXDate TDBXDateValue
GetDouble SetDouble Double TDBXDoubleValue
GetInt16 SetInt16 Int16 TDBXInt16Value
GetInt32 SetInt32 Int32 TDBXInt32Value
GetInt64 SetInt64 Int64 TDBXInt64Value
GetSingle SetSingle Single TDBXSingleValue
SetString GetString string TDBXStringValue, TDBXWideCharsValue, TDBXWideStringValue
GetTime SetTime TDBXTime TDBXTimeValue
GetTimeStamp SetTimeStamp TSQLTimeStamp TDBXTimeStampValue
GetWideString SetWideString UnicodeString (same as string) TDBXStringValue, TDBXWideCharsValue, TDBXWideStringValue

 

String Value Types

Of the five DBXValue types that represent strings, you need only use TDBXAnsCharsValue to pass AnsiString values and TDBXWideCharsValue to pass UnicodeString/string values. The following table shows that these two types are always passed to server methods even if the method is declared with one of the other string types.

Declared Type Actual Type
TDBXAnsiCharsValue TDBXAnsiCharsValue
TDBXAnsiStringValue TDBXAnsiCharsValue
TDBXStringValue TDBXWideCharsValue
TDBXWideCharsValue TDBXWideCharsValue
TDBXWideStringValue TDBXWideCharsValue

Sample Client And Server Applications

The sample server has a few simple server methods for passing values (including null), and two informational server methods.  In order to support various DBXValue types, I’ve implemented a generic server method base class:

{$METHODINFO ON}
  TTestBasicDBXValueType = class(TComponent)
  strict protected
    function EqualValues(I: TValue; J: TValue): Boolean; virtual;
    function GetValue(I: T): TValue; virtual; abstract;
    procedure SetValue(I: T; Value: TValue); virtual; abstract;
  public
    // Server methods to pass values (including null)
    function IsEqual(I: T; J: T): Boolean;
    function Echo(I: T): TValue;
    procedure Swap(I: T; J: T);
    function IsNull(I: T): Boolean;
    procedure SetNull(I: T);
    // Server method to get the DBXValue parameter type names
    procedure GetTypeNames(I: T; ADeclaredName, AActualName: TDBXStringValue);
    // Server method to try DBXValue methods like GetInt32 and SetInt32
    function TryGetAndSet(I: T): TDataSet;
  end;
{$METHODINFO OFF}

Then I’ve used TTestBasicDBXValueType to declare and implement server methods classes for a variety of DBXValue types, such as TDBXInt32Value, TTestDBXDateValue , etc.

  TTestDBXInt32Value = class(TTestBasicDBXValueType)
  strict protected
    function GetValue(I: TDBXInt32Value): Int32; override;
    procedure SetValue(I: TDBXInt32Value; Value: Int32); override;
  end;

  TTestDBXDateValue = class(TTestBasicDBXValueType)
  strict protected
    function GetValue(I: TDBXDateValue): TDBXDate; override;
    procedure SetValue(I: TDBXDateValue; Value: TDBXDate); override;
  end;

Consult the sample server to see how I’ve implemented the "plumbing" to make these classes callable by a DataSnap client. As in the “Basic” types sample server, the implementation is unconventional because the TDSServerClass component is not used.

The sample client tests the generated methods by calling them with sample values and verifying the results. Consult the sample for implementation details. Here is screen shot of the running server and client:

The following table shows the parameter types and return types demonstrated in the sample client and server:

Type (in/out) var out Result
TDBXAnsiCharsValue X      
TDBXAnsiStringValue X      
TDBXBcdValue X      
TDBXBooleanValue X      
TDBXDateValue X      
TDBXDoubleValue X      
TDBXInt16Value X      
TDBXInt32Value X      
TDBXInt64Value X      
TDBXSingleValue X      
TDBXStringValue X      
TDBXTimeValue X      
TDBXTimeStampValue X      
TDBXWideCharsValue X      
TDBXWideStringValue X      

That’s all for now.  I plan on covering the collection types in my next post.

{ 3 } Comments

  1. Luis Branca | March 17, 2009 at 12:14 am | Permalink

    Wouldn’t be helpful to also have a basic TDBXDateTimeValue?
    It may seem that TDBXTimeStampValue is enough, but the issue is that an implicit cast of a TimeStamp into a database field type of DATE (basically a DateTime), basically kills the usage of any index on those fields.

    Further details in
    http://qc.embarcadero.com/wc/qcmain.aspx?d=34745

    Maybe there’s a workaround, but I just haven’t found it yet.

  2. Jim Tierney | March 18, 2009 at 2:11 pm | Permalink

    I don’t know if TDBXDateTimeValue is needed to fix this problem. However, to make sure that R&D is aware of the performance/index issue, I’ve added a comment to the internal bug report associated with QC 34745.

  3. Luis Branca | March 19, 2009 at 1:58 am | Permalink

    I’m also not sure if it will be absolutely required to have it, but it just *seems* to have it’s root on the lack of such basic DBXValue type (TDBXDateTimeValue). I’m quite probably way out on this assumption… but sometimes all it takes is a different perspective to solve something :)
    Anyway, thank you for rising this with R&D.

{ 1 } Trackback

  1. [...] Jim Tierney from Embarcadero has already discussed different DataSnap parameter types on his blog and during recent CodeRage5 conference session "DataSnap: Features and Integration with User [...]

Post a Comment

Your email is never published nor shared. Required fields are marked *

Bad Behavior has blocked 26 access attempts in the last 7 days.

Close