<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>Jim Tierney</title>
	<atom:link href="http://blogs.embarcadero.com/jimtierney/feed" rel="self" type="application/rss+xml" />
	<link>http://blogs.embarcadero.com/jimtierney</link>
	<description></description>
	<pubDate>Fri, 14 Oct 2011 20:20:15 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.2</generator>
	<language>en-US</language>
			<item>
		<title>LiveBindings:  FillList using enumerable objects</title>
		<link>http://blogs.embarcadero.com/jimtierney/2011/10/14/31608</link>
		<comments>http://blogs.embarcadero.com/jimtierney/2011/10/14/31608#comments</comments>
		<pubDate>Fri, 14 Oct 2011 19:59:41 +0000</pubDate>
		<dc:creator>Jim Tierney</dc:creator>
		
		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[LiveBindings]]></category>

		<category><![CDATA[XE2]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/jimtierney/?p=31608</guid>
		<description><![CDATA[The previous post introduced a utility method called FillList and showed how to call it using BindScopeDB1 as the source component.  TBindScopeDB allows TBindList to work with a TDataSet.
This post shows a version of FillList which can work with enumerable objects such at TStrings or TList&#60;&#62; (an object is enumerable if it implements GetEnumerator).   TBindScope [...]]]></description>
			<content:encoded><![CDATA[<p>The previous post introduced a utility method called FillList and showed how to call it using BindScopeDB1 as the source component.  TBindScopeDB allows TBindList to work with a TDataSet.</p>
<p>This post shows a version of FillList which can work with enumerable objects such at TStrings or TList&lt;&gt; (an object is enumerable if it implements GetEnumerator).   TBindScope is used instead of TBindScopeDB.  </p>
<p>Here is a FillList method which can populate a list control from an enumerable object: </p>
<pre><span style="color: red"><strong>procedure</strong></span> FillList<span style="color: blue;font-size: xx-small"><strong>(</strong></span>AControl<span style="color: blue;font-size: xx-small"><strong>:</strong></span> TComponent<span style="color: blue;font-size: xx-small"><strong>;</strong></span> <span style="color: red"><strong>const</strong></span> AControlExpression<span style="color: blue;font-size: xx-small"><strong>:</strong></span> <span style="color: red"><strong>string</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span>
  AEnumerableObject<span style="color: blue;font-size: xx-small"><strong>:</strong></span> TObject<span style="color: blue;font-size: xx-small"><strong>;</strong></span> <span style="color: red"><strong>const</strong></span> ASourceExpression<span style="color: blue;font-size: xx-small"><strong>:</strong></span> <span style="color: red"><strong>string</strong></span><span style="color: blue;font-size: xx-small"><strong>)</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span> overload<span style="color: blue;font-size: xx-small"><strong>;</strong></span>
<span style="color: red"><strong>var</strong></span>
  LBindList<span style="color: blue;font-size: xx-small"><strong>:</strong></span> TBindList<span style="color: blue;font-size: xx-small"><strong>;</strong></span>
  LBindScope<span style="color: blue;font-size: xx-small"><strong>:</strong></span> TBindScope<span style="color: blue;font-size: xx-small"><strong>;</strong></span>
  I<span style="color: blue;font-size: xx-small"><strong>:</strong></span> Integer<span style="color: blue;font-size: xx-small"><strong>;</strong></span>
<span style="color: red"><strong>begin</strong></span>
  LBindScope <span style="color: blue;font-size: xx-small"><strong>:</strong></span><span style="color: blue;font-size: xx-small">=</span> TBindScope<span style="color: blue;font-size: xx-small"><strong><span style="color: blue;font-size: xx-small"><strong>.</strong></span></strong></span>Create<span style="color: blue;font-size: xx-small"><strong>(</strong></span><span style="color: red"><strong>nil</strong></span><span style="color: blue;font-size: xx-small"><strong>)</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span>
  LBindList <span style="color: blue;font-size: xx-small"><strong>:</strong></span><span style="color: blue;font-size: xx-small">=</span> TBindList<span style="color: blue;font-size: xx-small"><strong><span style="color: blue;font-size: xx-small"><strong>.</strong></span></strong></span>Create<span style="color: blue;font-size: xx-small"><strong>(</strong></span><span style="color: red"><strong>nil</strong></span><span style="color: blue;font-size: xx-small"><strong>)</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span>
  <span style="color: red"><strong>try</strong></span>
    <span style="color: green"><em>// Turn off auto properties.
</em></span>    LBindList<span style="color: blue;font-size: xx-small"><strong><span style="color: blue;font-size: xx-small"><strong>.</strong></span></strong></span>AutoFill <span style="color: blue;font-size: xx-small"><strong>:</strong></span><span style="color: blue;font-size: xx-small">=</span> False<span style="color: blue;font-size: xx-small"><strong>;</strong></span>
    LBindList<span style="color: blue;font-size: xx-small"><strong><span style="color: blue;font-size: xx-small"><strong>.</strong></span></strong></span>AutoActivate <span style="color: blue;font-size: xx-small"><strong>:</strong></span><span style="color: blue;font-size: xx-small">=</span> False<span style="color: blue;font-size: xx-small"><strong>;</strong></span>
    LBindList<span style="color: blue;font-size: xx-small"><strong><span style="color: blue;font-size: xx-small"><strong>.</strong></span></strong></span>ControlComponent <span style="color: blue;font-size: xx-small"><strong>:</strong></span><span style="color: blue;font-size: xx-small">=</span> AControl<span style="color: blue;font-size: xx-small"><strong>;</strong></span>
    <span style="color: green"><em>// Scope references the enumerable object
</em></span>    LBindScope<span style="color: blue;font-size: xx-small"><strong><span style="color: blue;font-size: xx-small"><strong>.</strong></span></strong></span>DataObject <span style="color: blue;font-size: xx-small"><strong>:</strong></span><span style="color: blue;font-size: xx-small">=</span> AEnumerableObject<span style="color: blue;font-size: xx-small"><strong>;</strong></span>
    LBindList<span style="color: blue;font-size: xx-small"><strong><span style="color: blue;font-size: xx-small"><strong>.</strong></span></strong></span>SourceComponent <span style="color: blue;font-size: xx-small"><strong>:</strong></span><span style="color: blue;font-size: xx-small">=</span> LBindScope<span style="color: blue;font-size: xx-small"><strong>;</strong></span>
    <span style="color: red"><strong>with</strong></span> LBindList<span style="color: blue;font-size: xx-small"><strong><span style="color: blue;font-size: xx-small"><strong>.</strong></span></strong></span>FormatExpressions<span style="color: blue;font-size: xx-small"><strong><span style="color: blue;font-size: xx-small"><strong>.</strong></span></strong></span>AddExpression <span style="color: red"><strong>do</strong></span>
    <span style="color: red"><strong>begin</strong></span>
      SourceExpression <span style="color: blue;font-size: xx-small"><strong>:</strong></span><span style="color: blue;font-size: xx-small">=</span> ASourceExpression<span style="color: blue;font-size: xx-small"><strong>;</strong></span>
      ControlExpression <span style="color: blue;font-size: xx-small"><strong>:</strong></span><span style="color: blue;font-size: xx-small">=</span> AControlExpression<span style="color: blue;font-size: xx-small"><strong>;</strong></span>
    <span style="color: red"><strong>end</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span>
    LBindList<span style="color: blue;font-size: xx-small"><strong><span style="color: blue;font-size: xx-small"><strong>.</strong></span></strong></span>FillList<span style="color: blue;font-size: xx-small"><strong>;</strong></span>
  <span style="color: red"><strong>finally</strong></span>
    LBindList<span style="color: blue;font-size: xx-small"><strong><span style="color: blue;font-size: xx-small"><strong>.</strong></span></strong></span>Free<span style="color: blue;font-size: xx-small"><strong>;</strong></span>
    LBindScope<span style="color: blue;font-size: xx-small"><strong><span style="color: blue;font-size: xx-small"><strong>.</strong></span></strong></span>Free<span style="color: blue;font-size: xx-small"><strong>;</strong></span>
  <span style="color: red"><strong>end</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span>
<span style="color: red"><strong>end</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span></pre>
<p>Call FillList as follows to populate a ListBox or ComboBox with the values from a TStrings:</p>
<pre><span style="color: red"><strong>procedure</strong></span> ListStrings<span style="color: blue;font-size: xx-small"><strong>(</strong></span>AListControl<span style="color: blue;font-size: xx-small"><strong>:</strong></span> TControl<span style="color: blue;font-size: xx-small"><strong>)</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span>
<span style="color: red"><strong>var</strong></span>
  LStrings<span style="color: blue;font-size: xx-small"><strong>:</strong></span> TStrings<span style="color: blue;font-size: xx-small"><strong>;</strong></span>
<span style="color: red"><strong>begin</strong></span>
  LStrings <span style="color: blue;font-size: xx-small"><strong>:</strong></span><span style="color: blue;font-size: xx-small">=</span> TStringList<span style="color: blue;font-size: xx-small"><strong><span style="color: blue;font-size: xx-small"><strong>.</strong></span></strong></span>Create<span style="color: blue;font-size: xx-small"><strong>;</strong></span>
  <span style="color: red"><strong>try</strong></span>
    LStrings<span style="color: blue;font-size: xx-small"><strong><span style="color: blue;font-size: xx-small"><strong>.</strong></span></strong></span>DelimitedText <span style="color: blue;font-size: xx-small"><strong>:</strong></span><span style="color: blue;font-size: xx-small">=</span> <span style="color: purple">'one,two,three,four,five,six'</span><span style="color: blue;font-size: xx-small"><strong>;</strong></span>

    FillList<span style="color: blue;font-size: xx-small"><strong>(</strong></span>AListControl<span style="color: blue;font-size: xx-small"><strong>,</strong></span> <span style="color: purple">'Text'</span><span style="color: blue;font-size: xx-small"><strong>,</strong></span> LStrings<span style="color: blue;font-size: xx-small"><strong>,</strong></span> <span style="color: purple">'Current'</span><span style="color: blue;font-size: xx-small"><strong>)</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span>
  <span style="color: red"><strong>finally</strong></span>
    LStrings<span style="color: blue;font-size: xx-small"><strong><span style="color: blue;font-size: xx-small"><strong>.</strong></span></strong></span>Free<span style="color: blue;font-size: xx-small"><strong>;</strong></span>
  <span style="color: red"><strong>end</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span>
<span style="color: red"><strong>end</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span></pre>
<p>&#8216;Text&#8217; references the list item text.   &#8216;Current&#8217; references the property Current of TStringsEnumerator.</p>
<p>Instead of TStrings we can also use a generic collection of string:</p>
<pre><span style="color: red"><strong>procedure</strong></span> ListStrings<span style="color: blue;font-size: xx-small"><strong>(</strong></span>AListControl<span style="color: blue;font-size: xx-small"><strong>:</strong></span> TControl<span style="color: blue;font-size: xx-small"><strong>)</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span>
<span style="color: red"><strong>var</strong></span>
  LStrings<span style="color: blue;font-size: xx-small"><strong>:</strong></span> TList<span style="color: blue;font-size: xx-small">&lt;</span><span style="color: red"><strong>string</strong></span><span style="color: blue;font-size: xx-small">&gt;</span><span style="color: blue;font-size: xx-small"><strong>;</strong></span>
<span style="color: red"><strong>begin</strong></span>
  LStrings <span style="color: blue;font-size: xx-small"><strong>:</strong></span><span style="color: blue;font-size: xx-small">=</span> TList<span style="color: blue;font-size: xx-small">&lt;</span><span style="color: red"><strong>string</strong></span><span style="color: blue;font-size: xx-small">&gt;</span><span style="color: blue;font-size: xx-small"><strong><span style="color: blue;font-size: xx-small"><strong>.</strong></span></strong></span>Create<span style="color: blue;font-size: xx-small"><strong>;</strong></span>
  <span style="color: red"><strong>try</strong></span>
    LStrings<span style="color: blue;font-size: xx-small"><strong><span style="color: blue;font-size: xx-small"><strong>.</strong></span></strong></span>AddRange<span style="color: blue;font-size: xx-small"><strong>(</strong></span>
     TArray<span style="color: blue;font-size: xx-small">&lt;</span><span style="color: red"><strong>string</strong></span><span style="color: blue;font-size: xx-small">&gt;</span><span style="color: blue;font-size: xx-small"><strong><span style="color: blue;font-size: xx-small"><strong>.</strong></span></strong></span>Create<span style="color: blue;font-size: xx-small"><strong>(</strong></span><span style="color: purple">'one'</span><span style="color: blue;font-size: xx-small"><strong>,</strong></span><span style="color: purple">'two'</span><span style="color: blue;font-size: xx-small"><strong>,</strong></span><span style="color: purple">'three'</span><span style="color: blue;font-size: xx-small"><strong>)</strong></span><span style="color: blue;font-size: xx-small"><strong>)</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span>

    FillList<span style="color: blue;font-size: xx-small"><strong>(</strong></span>AListControl<span style="color: blue;font-size: xx-small"><strong>,</strong></span> <span style="color: purple">'Text'</span><span style="color: blue;font-size: xx-small"><strong>,</strong></span> LStrings<span style="color: blue;font-size: xx-small"><strong>,</strong></span> <span style="color: purple">'Current'</span><span style="color: blue;font-size: xx-small"><strong>)</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span>
  <span style="color: red"><strong>finally</strong></span>
    LStrings<span style="color: blue;font-size: xx-small"><strong><span style="color: blue;font-size: xx-small"><strong>.</strong></span></strong></span>Free<span style="color: blue;font-size: xx-small"><strong>;</strong></span>
  <span style="color: red"><strong>end</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span>
<span style="color: red"><strong>end</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span></pre>
<p>And also a generic collection of object:</p>
<pre><span style="color: red"><strong>type</strong></span>
  TSampleObject <span style="color: blue;font-size: xx-small">=</span> <span style="color: red"><strong>class</strong></span>
  <span style="color: red"><strong>private</strong></span>
    FStringProp<span style="color: blue;font-size: xx-small"><strong>:</strong></span> <span style="color: red"><strong>string</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span>
    FIntegerProp<span style="color: blue;font-size: xx-small"><strong>:</strong></span> Integer<span style="color: blue;font-size: xx-small"><strong>;</strong></span>
  <span style="color: red"><strong>public</strong></span>
    <span style="color: red"><strong>constructor</strong></span> Create<span style="color: blue;font-size: xx-small"><strong>(</strong></span>AIntegerProp<span style="color: blue;font-size: xx-small"><strong>:</strong></span> Integer<span style="color: blue;font-size: xx-small"><strong>)</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span>
    <span style="color: red"><strong>property</strong></span> StringProp<span style="color: blue;font-size: xx-small"><strong>:</strong></span> <span style="color: red"><strong>string</strong></span> read FStringProp<span style="color: blue;font-size: xx-small"><strong>;</strong></span>
    <span style="color: red"><strong>property</strong></span> IntegerProp<span style="color: blue;font-size: xx-small"><strong>:</strong></span> Integer read FIntegerProp<span style="color: blue;font-size: xx-small"><strong>;</strong></span>
  <span style="color: red"><strong>end</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span>

<span style="color: red"><strong>procedure</strong></span> ListSampleObjects<span style="color: blue;font-size: xx-small"><strong>(</strong></span>AListControl<span style="color: blue;font-size: xx-small"><strong>:</strong></span> TControl<span style="color: blue;font-size: xx-small"><strong>)</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span>
<span style="color: red"><strong>var</strong></span>
  LList<span style="color: blue;font-size: xx-small"><strong>:</strong></span> TList<span style="color: blue;font-size: xx-small">&lt;</span>TSampleObject<span style="color: blue;font-size: xx-small">&gt;</span><span style="color: blue;font-size: xx-small"><strong>;</strong></span>
  I<span style="color: blue;font-size: xx-small"><strong>:</strong></span> Integer<span style="color: blue;font-size: xx-small"><strong>;</strong></span>
<span style="color: red"><strong>begin</strong></span>
  LList <span style="color: blue;font-size: xx-small"><strong>:</strong></span><span style="color: blue;font-size: xx-small">=</span> TObjectList<span style="color: blue;font-size: xx-small">&lt;</span>TSampleObject<span style="color: blue;font-size: xx-small">&gt;</span><span style="color: blue;font-size: xx-small"><strong><span style="color: blue;font-size: xx-small"><strong>.</strong></span></strong></span>Create<span style="color: blue;font-size: xx-small"><strong>;</strong></span> <span style="color: green"><em>// Owns objects
</em></span>  <span style="color: red"><strong>try</strong></span>
    <span style="color: red"><strong>for</strong></span> I <span style="color: blue;font-size: xx-small"><strong>:</strong></span><span style="color: blue;font-size: xx-small">=</span> <span style="color: brown">1</span> <span style="color: red"><strong>to</strong></span> <span style="color: brown">10</span> <span style="color: red"><strong>do</strong></span>
      LList<span style="color: blue;font-size: xx-small"><strong><span style="color: blue;font-size: xx-small"><strong>.</strong></span></strong></span>Add<span style="color: blue;font-size: xx-small"><strong>(</strong></span>TSampleObject<span style="color: blue;font-size: xx-small"><strong><span style="color: blue;font-size: xx-small"><strong>.</strong></span></strong></span>Create<span style="color: blue;font-size: xx-small"><strong>(</strong></span>I<span style="color: blue;font-size: xx-small"><strong>)</strong></span><span style="color: blue;font-size: xx-small"><strong>)</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span>

    FillList<span style="color: blue;font-size: xx-small"><strong>(</strong></span>AListControl<span style="color: blue;font-size: xx-small"><strong>,</strong></span> <span style="color: purple">'Text'</span><span style="color: blue;font-size: xx-small"><strong>,</strong></span> LList<span style="color: blue;font-size: xx-small"><strong>,</strong></span> <span style="color: purple">'ToStr(Current.IntegerProp) + ": " + Current.StringProp'</span><span style="color: blue;font-size: xx-small"><strong>)</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span>
  <span style="color: red"><strong>finally</strong></span>
    LList<span style="color: blue;font-size: xx-small"><strong><span style="color: blue;font-size: xx-small"><strong>.</strong></span></strong></span>Free<span style="color: blue;font-size: xx-small"><strong>;</strong></span>
  <span style="color: red"><strong>end</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span>
<span style="color: red"><strong>end</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span></pre>
<p>As mentioned in the previous post,  you will need to use FMX.Binding.Editors. For VCL projects, use VCL.Binding.Editors.</p>
<p>A sample project using FillList is available on sourceforge:</p>
<div class="mceTemp">
<div class="mceTemp"><a href="https://radstudiodemos.svn.sourceforge.net/svnroot/radstudiodemos/branches/RadStudio_XE2/LiveBindings/bindlist">https://radstudiodemos.svn.sourceforge.net/svnroot/radstudiodemos/branches/RadStudio_XE2/LiveBindings/bindlist</a></div>
<div class="mceTemp">The project name is BindListUtilsSampleProject.dpr.</div>
</div>
<p class="akst_link"><a href="http://blogs.embarcadero.com/jimtierney/?p=31608&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_31608" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=LiveBindings%3A%20%20FillList%20using%20enumerable%20objects&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fjimtierney%2F2011%2F10%2F14%2F31608" id="akst_email_31608" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/jimtierney/2011/10/14/31608/feed</wfw:commentRss>
		</item>
		<item>
		<title>LiveBindings: Code to create TBindLink and fill a Listbox</title>
		<link>http://blogs.embarcadero.com/jimtierney/2011/10/03/31601</link>
		<comments>http://blogs.embarcadero.com/jimtierney/2011/10/03/31601#comments</comments>
		<pubDate>Mon, 03 Oct 2011 21:33:20 +0000</pubDate>
		<dc:creator>Jim Tierney</dc:creator>
		
		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[LiveBindings]]></category>

		<category><![CDATA[XE2]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/jimtierney/?p=31601</guid>
		<description><![CDATA[The previous post described how to configure TBindList in the designer.  This post describes how to use TBindList in code.
Here is a method to fill a listbox using a TBindList component:
procedure FillList(AControl: TComponent; const AControlExpression: string;
  ASource: TBaseBindScopeComponent; const ASourceExpression: string; const ASourceMemberName: string = '');
var
  LBindList: TBindList;
begin
  LBindList := TBindList.Create(nil);
  try
 [...]]]></description>
			<content:encoded><![CDATA[<p>The previous post described how to configure TBindList in the designer.  This post describes how to use TBindList in code.</p>
<p>Here is a method to fill a listbox using a TBindList component:</p>
<pre><span style="color: red"><strong>procedure</strong></span> FillList<span style="color: blue;font-size: xx-small"><strong>(</strong></span>AControl<span style="color: blue;font-size: xx-small"><strong>:</strong></span> TComponent<span style="color: blue;font-size: xx-small"><strong>;</strong></span> <span style="color: red"><strong>const</strong></span> AControlExpression<span style="color: blue;font-size: xx-small"><strong>:</strong></span> <span style="color: red"><strong>string</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span>
  ASource<span style="color: blue;font-size: xx-small"><strong>:</strong></span> TBaseBindScopeComponent<span style="color: blue;font-size: xx-small"><strong>;</strong></span> <span style="color: red"><strong>const</strong></span> ASourceExpression<span style="color: blue;font-size: xx-small"><strong>:</strong></span> <span style="color: red"><strong>string</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span> <span style="color: red"><strong>const</strong></span> ASourceMemberName<span style="color: blue;font-size: xx-small"><strong>:</strong></span> <span style="color: red"><strong>string</strong></span> <span style="color: blue;font-size: xx-small">=</span> <span style="color: purple">''</span><span style="color: blue;font-size: xx-small"><strong>)</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span>
<span style="color: red"><strong>var</strong></span>
  LBindList<span style="color: blue;font-size: xx-small"><strong>:</strong></span> TBindList<span style="color: blue;font-size: xx-small"><strong>;</strong></span>
<span style="color: red"><strong>begin</strong></span>
  LBindList <span style="color: blue;font-size: xx-small"><strong>:</strong></span><span style="color: blue;font-size: xx-small">=</span> TBindList<span style="color: blue;font-size: xx-small"><strong><span style="color: blue;font-size: xx-small"><strong>.</strong></span></strong></span>Create<span style="color: blue;font-size: xx-small"><strong>(</strong></span><span style="color: red"><strong>nil</strong></span><span style="color: blue;font-size: xx-small"><strong>)</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span>
  <span style="color: red"><strong>try</strong></span>
    <span style="color: green"><em>// Turn off auto properties.
</em></span>    LBindList<span style="color: blue;font-size: xx-small"><strong><span style="color: blue;font-size: xx-small"><strong>.</strong></span></strong></span>AutoFill <span style="color: blue;font-size: xx-small"><strong>:</strong></span><span style="color: blue;font-size: xx-small">=</span> False<span style="color: blue;font-size: xx-small"><strong>;</strong></span>
    LBindList<span style="color: blue;font-size: xx-small"><strong><span style="color: blue;font-size: xx-small"><strong>.</strong></span></strong></span>AutoActivate <span style="color: blue;font-size: xx-small"><strong>:</strong></span><span style="color: blue;font-size: xx-small">=</span> False<span style="color: blue;font-size: xx-small"><strong>;</strong></span>
    LBindList<span style="color: blue;font-size: xx-small"><strong><span style="color: blue;font-size: xx-small"><strong>.</strong></span></strong></span>ControlComponent <span style="color: blue;font-size: xx-small"><strong>:</strong></span><span style="color: blue;font-size: xx-small">=</span> AControl<span style="color: blue;font-size: xx-small"><strong>;</strong></span>
    LBindList<span style="color: blue;font-size: xx-small"><strong><span style="color: blue;font-size: xx-small"><strong>.</strong></span></strong></span>SourceComponent <span style="color: blue;font-size: xx-small"><strong>:</strong></span><span style="color: blue;font-size: xx-small">=</span> ASource<span style="color: blue;font-size: xx-small"><strong>;</strong></span>
    LBindList<span style="color: blue;font-size: xx-small"><strong><span style="color: blue;font-size: xx-small"><strong>.</strong></span></strong></span>SourceMemberName <span style="color: blue;font-size: xx-small"><strong>:</strong></span><span style="color: blue;font-size: xx-small">=</span> ASourceMemberName<span style="color: blue;font-size: xx-small"><strong>;</strong></span>
    <span style="color: red"><strong>with</strong></span> LBindList<span style="color: blue;font-size: xx-small"><strong><span style="color: blue;font-size: xx-small"><strong>.</strong></span></strong></span>FormatExpressions<span style="color: blue;font-size: xx-small"><strong><span style="color: blue;font-size: xx-small"><strong>.</strong></span></strong></span>AddExpression <span style="color: red"><strong>do</strong></span>
    <span style="color: red"><strong>begin</strong></span>
      SourceExpression <span style="color: blue;font-size: xx-small"><strong>:</strong></span><span style="color: blue;font-size: xx-small">=</span> ASourceExpression<span style="color: blue;font-size: xx-small"><strong>;</strong></span>
      ControlExpression <span style="color: blue;font-size: xx-small"><strong>:</strong></span><span style="color: blue;font-size: xx-small">=</span> AControlExpression<span style="color: blue;font-size: xx-small"><strong>;</strong></span>
    <span style="color: red"><strong>end</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span>
    LBindList<span style="color: blue;font-size: xx-small"><strong><span style="color: blue;font-size: xx-small"><strong>.</strong></span></strong></span>FillList<span style="color: blue;font-size: xx-small"><strong>;</strong></span>
  <span style="color: red"><strong>finally</strong></span>
    LBindList<span style="color: blue;font-size: xx-small"><strong><span style="color: blue;font-size: xx-small"><strong>.</strong></span></strong></span>Free<span style="color: blue;font-size: xx-small"><strong>;</strong></span>
  <span style="color: red"><strong>end</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span>
<span style="color: red"><strong>end</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span></pre>
<p>You will need a TBindScopeDB component which is connected to a TDataSource. Call FillList as follows to populate a listbox with the value of the Category field:</p>
<pre>  FillList<span style="color: blue;font-size: xx-small"><strong>(</strong></span>ListBox1<span style="color: blue;font-size: xx-small"><strong>,</strong></span> <span style="color: purple">'Text'</span><span style="color: blue;font-size: xx-small"><strong>,</strong></span> BindScopeDB1<span style="color: blue;font-size: xx-small"><strong>,</strong></span> <span style="color: purple">'AsString'</span><span style="color: blue;font-size: xx-small"><strong>,</strong></span> <span style="color: purple">'Category'</span><span style="color: blue;font-size: xx-small"><strong>)</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span></pre>
<p>When using this code in a FireMonkey project, you will need to use FMX.Bind.Editors. For VCL projects, use VCL.Bind.Editors.</p>
<p>These units register editors which TBindList uses to add items to a TListBox. These units also register editors for a TComboBox.  Use the following line of code to populate a combo box.</p>
<pre>  FillList<span style="color: blue;font-size: xx-small"><strong>(</strong></span>ComboBox1<span style="color: blue;font-size: xx-small"><strong>,</strong></span> <span style="color: purple">'Text'</span><span style="color: blue;font-size: xx-small"><strong>,</strong></span> BindScopeDB1<span style="color: blue;font-size: xx-small"><strong>,</strong></span> <span style="color: purple">'AsString'</span><span style="color: blue;font-size: xx-small"><strong>,</strong></span> <span style="color: purple">'Category'</span><span style="color: blue;font-size: xx-small"><strong>)</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span></pre>
<p>VCL.Bind.Editors also registers an editor for TListView.  Use the following line of code to populate a list view:</p>
<pre>  FillList<span style="color: blue;font-size: xx-small"><strong>(</strong></span>ListView1<span style="color: blue;font-size: xx-small"><strong>,</strong></span> <span style="color: purple">'Caption'</span><span style="color: blue;font-size: xx-small"><strong>,</strong></span> BindScopeDB1<span style="color: blue;font-size: xx-small"><strong>,</strong></span> <span style="color: purple">'AsString'</span><span style="color: blue;font-size: xx-small"><strong>,</strong></span> <span style="color: purple">'Category'</span><span style="color: blue;font-size: xx-small"><strong>)</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span></pre>
<p>The last parameter to the FillList method is optional. When excluded, TBindList will evaluate against TDataSet instead of TField.  The following code fills a listbox with values from two different fields:</p>
<pre>  FillList<span style="color: blue;font-size: xx-small"><strong>(</strong></span>ListBox1<span style="color: blue;font-size: xx-small"><strong>,</strong></span> <span style="color: purple">'Text'</span><span style="color: blue;font-size: xx-small"><strong>,</strong></span> BindScopeDB1<span style="color: blue;font-size: xx-small"><strong>,</strong></span> <span style="color: purple">'Category.AsString + " - " +  Common_Name.AsString'</span><span style="color: blue;font-size: xx-small"><strong>)</strong></span><span style="color: blue;font-size: xx-small"><strong>;</strong></span></pre>
<p>A sample project showing how to implemet and use the FillList method is available on sourceforge:</p>
<div class="mceTemp">
<div class="mceTemp"><a href="https://radstudiodemos.svn.sourceforge.net/svnroot/radstudiodemos/branches/RadStudio_XE2/LiveBindings/bindlist">https://radstudiodemos.svn.sourceforge.net/svnroot/radstudiodemos/branches/RadStudio_XE2/LiveBindings/bindlist</a></div>
<div class="mceTemp">The project name is BindListUtilsSampleProject.dpr.</div>
<div class="mceTemp">This project includes other versions of FillList besides the one shown in this post.   More about this in the next post.</div>
</div>
<p class="akst_link"><a href="http://blogs.embarcadero.com/jimtierney/?p=31601&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_31601" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=LiveBindings%3A%20Code%20to%20create%20TBindLink%20and%20fill%20a%20Listbox&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fjimtierney%2F2011%2F10%2F03%2F31601" id="akst_email_31601" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/jimtierney/2011/10/03/31601/feed</wfw:commentRss>
		</item>
		<item>
		<title>LiveBindings:  Fill a TListBox from a TClientDataSet at design time</title>
		<link>http://blogs.embarcadero.com/jimtierney/2011/09/30/31559</link>
		<comments>http://blogs.embarcadero.com/jimtierney/2011/09/30/31559#comments</comments>
		<pubDate>Fri, 30 Sep 2011 20:39:49 +0000</pubDate>
		<dc:creator>Jim Tierney</dc:creator>
		
		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[LiveBindings]]></category>

		<category><![CDATA[XE2]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/jimtierney/?p=31559</guid>
		<description><![CDATA[
TBindList can iterate through the records in a TClientDataSet and fill a TListBox.  Here is how to configure TBindList in the designer.
Drop a TClientDataSet and a TDataSource on a form.  Load some data into the dataset such as biolife.xml (Right click ClientDataSet1, choose "Load from MyBase table&#8230;", browse to the sample data directory and choose biolife.xml).   In the [...]]]></description>
			<content:encoded><![CDATA[<div class="mceTemp">
<p>TBindList can iterate through the records in a TClientDataSet and fill a TListBox.  Here is how to configure TBindList in the designer.</p>
<p>Drop a TClientDataSet and a TDataSource on a form.  Load some data into the dataset such as biolife.xml (Right click ClientDataSet1, choose "Load from MyBase table&#8230;", browse to the sample data directory and choose biolife.xml).   In the object inspector, set DataSource1.DataSet to ClientDataSet1.  Drop a TBindScopeDB component on the form and set BindScopeDB1.DataSource to DataSource1. </p>
<div id="attachment_31585" class="wp-caption alignnone" style="width: 510px"><a href="/files/2011/09/bindscopedb1_4710.png"><img src="/files/2011/09/bindscopedb1_4710.png" alt="BindScopeDB1 connected to DataSource1" width="500" height="131" /></a><p class="wp-caption-text">BindScopeDB1 connected to DataSource1</p></div>
</div>
<div class="mceTemp">Drop a TListBox on the form (this form is VCL but a FireMonkey form works the same way).  Select ListBox1 and you will see a command at the bottom of the object inspector called "New LIveBinding&#8230;".</div>
<div class="mceTemp">
<div id="attachment_31561" class="wp-caption alignnone" style="width: 510px"><a href="/files/2011/09/listbox1newlivebinding_4639.png"><img src="/files/2011/09/listbox1newlivebinding_4639.png" alt="New LiveBinding... command for ListBox1" width="500" height="228" /></a><p class="wp-caption-text">New LiveBinding... command for ListBox1</p></div>
</div>
<p>Click "New LiveBinding&#8230;" and choose TBindList.</p>
<div id="attachment_31563" class="wp-caption alignnone" style="width: 264px"><a href="/files/2011/09/newlivebindings1_4642.png"><img src="/files/2011/09/newlivebindings1_4642.png" alt="New LiveBinding dialog box" width="254" height="285" /></a><p class="wp-caption-text">New LiveBinding dialog box</p></div>
<p>Double click or press OK.  The New LiveBindings dialog creates a TBindingsList component and a TBindList component.  TBindingsList is a container for binding components just as TActionList is a container for actions.  Double click on TBindingsList to see the new TBindList component.</p>
<div id="attachment_31567" class="wp-caption alignnone" style="width: 510px"><a href="/files/2011/09/bindingslisteditor1_4647.png"><img src="/files/2011/09/bindingslisteditor1_4647.png" alt="TBindingsList contains a TBindList component" width="500" height="294" /></a><p class="wp-caption-text">TBindingsList contains a TBindList component</p></div>
<p>Click on BindListListBox11 to show the properties of the new TBindList component.   The ControlComponent property was set to ListBox1 by the "New LiveBinding&#8230;" command.</p>
<div id="attachment_31569" class="wp-caption alignnone" style="width: 510px"><a href="/files/2011/09/bindlistcontrolcomponent1_4650.png"><img src="/files/2011/09/bindlistcontrolcomponent1_4650.png" alt="BindList1 with ControlComponent set to ListBox1" width="500" height="162" /></a><p class="wp-caption-text">BindList1 with ControlComponent set to ListBox1</p></div>
<p>Use the object inspector to set the SourceComponent to BindScopeDB1.  Set SourceMemberName to the name of a field.  The SourceMemberName property editor should provide a drop down list of field names.  If not, then the data components are probably not connected (DataSource1.DataSet must be set to ClientDataSet1 and  BindScopeDB1.DataSource must be set to DataSource1).</p>
<p> </p>
<div id="attachment_31573" class="wp-caption alignnone" style="width: 250px"><a href="/files/2011/09/bindlistsourcecomponent_4656.png"><img src="/files/2011/09/bindlistsourcecomponent_4656.png" alt="BindList1 SourceComponent and SourceMemberName" width="240" height="349" /></a><p class="wp-caption-text">BindList1 SourceComponent and SourceMemberName</p></div>
<p>The final step is to enter the binding expressions.  Open the expressions editor by clicking the "Expressions&#8230;" command at the bottom of the object inspector.</p>
<div id="attachment_31575" class="wp-caption alignnone" style="width: 510px"><a href="/files/2011/09/expressionseditor1_4677.png"><img src="/files/2011/09/expressionseditor1_4677.png" alt="BindList1 Expressions Editor" width="500" height="216" /></a><p class="wp-caption-text">BindList1 Expressions Editor</p></div>
<p>Select the "Format" collection and click the "Add Expression" button to add a new binding expression.  Enter "Text" as the control expression.  Enter "AsString" as the source expression.</p>
<div id="attachment_31576" class="wp-caption alignnone" style="width: 510px"><a href="/files/2011/09/expressionseditor2_4689.png"><img src="/files/2011/09/expressionseditor2_4689.png" alt="BindList1 Format binding expression" width="500" height="216" /></a><p class="wp-caption-text">BindList1 Format binding expression</p></div>
<p>Be sure that you&#8217;ve added to the "Format" collection and not the "FormatControl" collection. </p>
<p>The buttons at the bottom of the window are used to test the expressions.  Click "Eval Source" to evaluate the expression "AsString" against the Category field.</p>
<div id="attachment_31577" class="wp-caption alignnone" style="width: 416px"><a href="/files/2011/09/expressionresult1_4695.png"><img src="/files/2011/09/expressionresult1_4695.png" alt="Expression Result window" width="406" height="273" /></a><p class="wp-caption-text">Expression Result Window</p></div>
<p>Close the Expression Result window.  Also close the expression editor. </p>
<p>At the bottom of the object inspector are two commands for trying out TBindList at design time.  Click "Fill List" to populate ListBox1.</p>
<div id="attachment_31578" class="wp-caption alignnone" style="width: 419px"><a href="/files/2011/09/filllist1_4698.png"><img src="/files/2011/09/filllist1_4698.png" alt="BindList1 &quot;Fill List&quot; command fills ListBox1" width="409" height="275" /></a><p class="wp-caption-text">BindList1 fills ListBox1</p></div>
<p>Now click "Clear List".</p>
<p>Run the project.  ListBox1 is populated with the values of the Category field. </p>
<div class="mceTemp">
<dl>
<dt><a href="/files/2011/09/bindlistrunning1_4701.png"><img src="/files/2011/09/bindlistrunning1_4701.png" alt="ListBox1 populated by BindList1 at runtime" width="500" height="288" /></a></dt>
<dd>ListBox1 populated by BindList1 at runtime</dd>
</dl>
<p>VCL and FireMonkey sample projects using TBindList are available on sourceforge:</p></div>
<div class="mceTemp">
<div class="mceTemp"><a href="https://radstudiodemos.svn.sourceforge.net/svnroot/radstudiodemos/branches/RadStudio_XE2/LiveBindings/bindlist">https://radstudiodemos.svn.sourceforge.net/svnroot/radstudiodemos/branches/RadStudio_XE2/LiveBindings/bindlist</a></div>
<div class="mceTemp">projects: fmx\BindListFMXProject.dpr, vcl\BindListVCLProject.dpr</div>
<div class="mceTemp"><a href="https://radstudiodemos.svn.sourceforge.net/svnroot/radstudiodemos/branches/RadStudio_XE2/LiveBindings/bindlist">https://radstudiodemos.svn.sourceforge.net/svnroot/radstudiodemos/branches/RadStudio_XE2/LiveBindings/collections</a></div>
</div>
<div>projects: fmx\SimpleListCollectionSampleProject.dpr, fmx\ListCollectionsSampleProject</div>
<div>The next post will be about using TBindList in code.</div>
<p class="akst_link"><a href="http://blogs.embarcadero.com/jimtierney/?p=31559&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_31559" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=LiveBindings%3A%20%20Fill%20a%20TListBox%20from%20a%20TClientDataSet%20at%20design%20time&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fjimtierney%2F2011%2F09%2F30%2F31559" id="akst_email_31559" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/jimtierney/2011/09/30/31559/feed</wfw:commentRss>
		</item>
		<item>
		<title>CodeRage 4 Samples</title>
		<link>http://blogs.embarcadero.com/jimtierney/2009/09/08/31536</link>
		<comments>http://blogs.embarcadero.com/jimtierney/2009/09/08/31536#comments</comments>
		<pubDate>Tue, 08 Sep 2009 18:54:36 +0000</pubDate>
		<dc:creator>Jim Tierney</dc:creator>
		
		<category><![CDATA[DataSnap]]></category>

		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[Delphi Prism]]></category>

		<category><![CDATA[Oxygene]]></category>

		<category><![CDATA[ADO.NET]]></category>

		<category><![CDATA[CodeRage]]></category>

		<category><![CDATA[Prism]]></category>

		<category><![CDATA[Server Methods]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/jimtierney/?p=31536</guid>
		<description><![CDATA[I&#8217;ve uploaded the sample DataSnap projects used in my CodeRage 4 sessions.&#160;&#160; 
Samples from "DataSnap Tooling" (Wednesday, September 9 at 7 pm PDT) are available here: http://cc.embarcadero.com/Item/27221.



Projects
Descriptions
Screen shots


EchoStringServer 
Simple console style DataSnap server with TCP/IP and HTTP support.
EchoStringServer.jpg


DelphiEchoStringClient
Simple client to call the "EchoString" DataSnap server method. May be used with EchoStringServer or with your own [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve uploaded the sample DataSnap projects used in my <a href="http://conferences.embarcadero.com/coderage">CodeRage 4</a> sessions.&nbsp;&nbsp; </p>
<p>Samples from "DataSnap Tooling" (Wednesday, September 9 at 7 pm PDT) are available here: <a title="http://cc.embarcadero.com/Item/27221" href="http://cc.embarcadero.com/Item/27221">http://cc.embarcadero.com/Item/27221</a>.</p>
<table cellspacing="2" cellpadding="2" border="1">
<tbody>
<tr>
<th valign="top" width="167">Projects</th>
<th valign="top" width="422">Descriptions</th>
<th valign="top" width="215">Screen shots</th>
</tr>
<tr>
<td valign="top" width="167">EchoStringServer </td>
<td valign="top" width="422">Simple console style DataSnap server with TCP/IP and HTTP support.</td>
<td valign="top" width="215"><a href="/files/2009/09/echostringserver_1981.jpg">EchoStringServer.jpg</a></td>
</tr>
<tr>
<td valign="top" width="167">DelphiEchoStringClient</td>
<td valign="top" width="422">Simple client to call the "EchoString" DataSnap server method. May be used with EchoStringServer or with your own server created with one of the DataSnap server wizards..</td>
<td valign="top" width="215"><a href="/files/2009/09/delphiechostringclient_1987.jpg">DelphiEchoStringClient.jpg</a></td>
</tr>
<tr>
<td valign="top" width="167">SampleProxyGenerator</td>
<td valign="top" width="422">Standalone VCL application to generate a Datasnap client proxy in Delphi or C++.&nbsp; Generates code just like the proxy generator integrated with TSQLConnection. </td>
<td valign="top" width="215"><a href="/files/2009/09/sampleproxygenerator_1984.jpg">SampleProxyGenerator.jpg</a></td>
</tr>
<tr>
<td valign="top" width="167">PrismEchoStringClient</td>
<td valign="top" width="422">Simple client to call the "EchoString" DataSnap server method. Works like DelphiEchoStringClient except using DBX/ADO.NET rather than native DBX.</td>
<td valign="top" width="215"><a href="/files/2009/09/prismechostringclient_1993.jpg">PrismEchoStringClient.jpg</a></td>
</tr>
<tr>
<td valign="top" width="167">SamplePrismProxyGenerator</td>
<td valign="top" width="422">Standalone Winform application to generate a DataSnap client proxy in Prism.&nbsp; Generates code just like the proxy generator integrated with the Prism Server Explorer.</td>
<td valign="top" width="215"><a href="/files/2009/09/sampleprismproxygenerator_1990.jpg">SamplePrismProxyGenerator.jpg</a></td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><p>Samples from "DataSnap Server Method Table Parameters" (Thursday, September 10 at 6 pm) are available here: <a title="http://cc.embarcadero.com/Item/27222" href="http://cc.embarcadero.com/Item/27222">http://cc.embarcadero.com/Item/27222</a>. </p>
<table cellspacing="2" cellpadding="2" border="1">
<tbody>
<tr>
<th valign="top" width="167">Projects</th>
<th valign="top" width="422">Descriptions</th>
<th valign="top" width="215">Screen shots</th>
</tr>
<tr>
<td valign="top" width="167">DataSnapTablesSampleServer</td>
<td valign="top" width="422">DataSnap server with server methods declared with different types and directions of table parameters (TDataSet, TDBXReader, TParams, out, var, return and in).</td>
<td valign="top" width="215"><a href="/files/2009/09/datasnaptablessampleserver_1996.jpg">DataSnapTablesSampleServer.jpg</a></td>
</tr>
<tr>
<td valign="top" width="167">DataSnapTablesListViewClient</td>
<td valign="top" width="422">DataSnap client that can call a server method to get a table then display the table in a ListView.&nbsp;&nbsp; The server method must pass a table back to the client using var or out parameters, or result.&nbsp; Use with DataSnapTablesSampleServer.</td>
<td valign="top" width="215"><a href="/files/2009/09/datasnaptableslistviewclient_2002.jpg">DataSnapTablesListViewClient.jpg</a></td>
</tr>
<tr>
<td valign="top" width="167">DataSnapTablesLoggingServer</td>
<td valign="top" width="422">DataSnap server that logs activity during a server method call (e.g.; enter server method, read table, exit server method). </p>
</td>
<td valign="top" width="215"><a href="/files/2009/09/datasnaptablesloggingserver_2008.jpg">DataSnapTablesLoggingServer.jpg</a></td>
</tr>
<tr>
<td valign="top" width="167">DataSnapTablesLoggingClient</td>
<td valign="top" width="422">DataSnap client that logs activity during a server method call (e.g.; call server method, read table, return from server method call). Use with DataSnapTablesLoggingServer.</td>
<td valign="top" width="215"><a href="/files/2009/09/datasnaptablesloggingclient_2011.jpg">DataSnapTablesLoggingClient.jpg</a></td>
</tr>
<tr>
<td valign="top" width="167">DataSnapTablesCDSClient</td>
<td valign="top" width="422">DataSnap client with components to populate a TClientDataSet from a server method result table, and display in a grid. Components include TSQLConnection, TSQLServerMethod, TDataSetProvider, TClientDataSet, TDataSource and TDBGrid. </p>
</td>
<td valign="top" width="215"><a href="/files/2009/09/datasnaptablescdsclient_1999.jpg">DataSnapTablesCDSClient.jpg</a></td>
</tr>
<tr>
<td valign="top" width="167">DataSnapTablesProxyClient</td>
<td valign="top" width="422">DataSnap client that calls some of the methods in DataSnapTablesLoggingServer using a client proxy class generated using the TSQLConnection "Generate DataSnap client classes" command. </p>
</td>
<td valign="top" width="215"><a href="/files/2009/09/datasnaptablesproxyclient_2005.jpg">DataSnapTablesProxyClient.jpg</a></td>
</tr>
</tbody>
</table>
<p class="akst_link"><a href="http://blogs.embarcadero.com/jimtierney/?p=31536&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_31536" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=CodeRage%204%20Samples&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fjimtierney%2F2009%2F09%2F08%2F31536" id="akst_email_31536" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/jimtierney/2009/09/08/31536/feed</wfw:commentRss>
		</item>
		<item>
		<title>DataSnap 2010 HTTP support with an ISAPI dll</title>
		<link>http://blogs.embarcadero.com/jimtierney/2009/08/20/31502</link>
		<comments>http://blogs.embarcadero.com/jimtierney/2009/08/20/31502#comments</comments>
		<pubDate>Thu, 20 Aug 2009 12:06:11 +0000</pubDate>
		<dc:creator>Jim Tierney</dc:creator>
		
		<category><![CDATA[Data Explorer]]></category>

		<category><![CDATA[DataSnap]]></category>

		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[WebBroker]]></category>

		<category><![CDATA[HTTP]]></category>

		<category><![CDATA[ServerMethods]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/jimtierney/?p=31502</guid>
		<description><![CDATA[With DataSnap in Delphi 2010, you can develop DataSnap clients and server that communicate over HTTP.  One way to implement the server is as an ISAPI dll.  I&#8217;ve been given permission to show this feature pre-release.  See  http://www.embarcadero.com/rad-studio-2010 for for more information about the upcoming release.
Click these links to skip ahead Configure IIS, Connect with [...]]]></description>
			<content:encoded><![CDATA[<p>With DataSnap in Delphi 2010, you can develop DataSnap clients and server that communicate over HTTP.  One way to implement the server is as an ISAPI dll.  I&#8217;ve been given permission to show this feature pre-release.  See  <a href="http://www.embarcadero.com/rad-studio-2010">http://www.embarcadero.com/rad-studio-2010</a> for for more information about the upcoming release.</p>
<p>Click these links to skip ahead <a href="#configureiis">Configure IIS</a>, <a href="#dataexplorer">Connect with Data Explorer</a>, <a href="#ancestors">Ancestors and DataModules</a>, <a href="#debugging">ISAPI debugging</a></p>
<p>In the File/New… dialog, double click “DataSnap WebBroker Application”</p>
<p><a href="/files/2009/08/datasnapisapinewitems_1857.jpg"><img src="/files/2009/08/datasnapisapinewitems_1857.jpg" alt="" width="552" height="413" /></a></p>
<p> </p>
<p>Check “ISAPI/NSAPI Dynamic link Library”,  “Add Server Methods Class” and “Include sample methods”.</p>
<p>Select TPersistent as the ancestor class for the server methods.  I will say <a href="#ancestors">more about the ancestor choices</a> later in this post.</p>
<p><a href="/files/2009/08/datasnapisapinewwebbroker_1860.jpg"><img src="/files/2009/08/datasnapisapinewwebbroker_1860.jpg" alt="" width="334" height="369" /></a></p>
<p>Click OK to create a new project.</p>
<p><a href="/files/2009/08/datasnapisapiprojectmanager_1863.jpg"><img src="/files/2009/08/datasnapisapiprojectmanager_1863.jpg" alt="" width="275" height="240" /></a></p>
<p> </p>
<p>The new project has two units.  ServerMethodsUnit implements the server methods for this DataSnap server.  There is a single server method called EchoString with a string parameter (see my previous posts to learn more about server method parameter types).</p>
<p><a href="/files/2009/08/datasnapisapiservermethodsunit_1865.jpg"><img src="/files/2009/08/datasnapisapiservermethodsunit_1865.jpg" alt="" width="492" height="452" /></a></p>
<p>The WebModule contains the components that make this ISAPI dll function as a DataSnap 2010 HTTP server. </p>
<p><a href="/files/2009/08/datasnapisapiwebmodule_1868.jpg"><img src="/files/2009/08/datasnapisapiwebmodule_1868.jpg" alt="" width="709" height="294" /></a></p>
<p> </p>
<p>DSServer1 and DSServerClass are the same components used in stand alone TCP/IP DataSnap servers.   DSHTTPWebDispatcher is new to  DataSnap 2010.  It is responsible for managing ISAPI/WebBroker HTTP requests and responses on behalf of the DataSnap Server. </p>
<p>Both DSHTTPWebDispatcher1 and DSServerClass1 components have their “Server” property set to “DSServer1”.  The DSServerClass1 component calls an event handler to get the type of the server methods class:</p>
<p><a href="/files/2009/08/datasnapisapidsserverclass1getclass_1871.jpg"><img src="/files/2009/08/datasnapisapidsserverclass1getclass_1871.jpg" alt="" width="614" height="162" /></a></p>
<p>The wizard has generated a complete ISAPI application so no changes are required to the project source code, however I do need to configure IIS.  </p>
<p><a name="configureiis">Configure IIS</a></p>
<p>Here is how I configure IIS 6.0 on my Vista x32 system.</p>
<p>If you haven’t enabled IIS on your system then use “Programs and features”/”Turn Windows features on or off” to install.</p>
<p>Start Internet Information Services (IIS) Manager.</p>
<p>Expand Connections nodes, right click on “Default Web Site”, choose “Add Virtual Directory”.</p>
<p>Enter an alias of “DSProject” an a physical path of "c:\DSProject".</p>
<p><a href="/files/2009/08/datasnapisapiaddvirtualdirectory_1874.jpg"><img src="/files/2009/08/datasnapisapiaddvirtualdirectory_1874.jpg" alt="" width="453" height="344" /></a></p>
<p>ISAPI must be enabled for this virtual directory.  Select the “DSProjects” Connections node.  Double click the “Handler Mappings” icon.  Click Actions/“Edit Handler Permissions…”.  Check “Execute”.</p>
<p>Directory browsing is convenient but not required.  Enable it for this example.  Select “DSProjects” Connections node.  Double click the “Directory Browsing” icon.  Click Actions/”Enable”.</p>
<p>Almost done configuring IIS.  Click on the root Connection node.  Double click the “ISAPI and CGI Restrictions” icon.  Click Actions/”Edit Feature Setting…”.  I have “Allow unspecified ISAPI modules” checked.  If you don’t check this then you will need to add to the list of ISAPI dlls recognized by IIS, after you have built your project. </p>
<p>Now go back to Delphi 2010 and set the output directory to the virtual directory physical path c:\DSProject. </p>
<p><a href="/files/2009/08/datasnapisapioutputdirectory_1877.jpg"><img src="/files/2009/08/datasnapisapioutputdirectory_1877.jpg" alt="" width="595" height="412" /></a></p>
<p>Build the project.</p>
<p>Browse to <a href="http://localhost/DSProject">http://localhost/DSProject</a> and, if you have enabled directory browsing, you should see the ISAPI dll.  Click it.  You should see a page like this:</p>
<p><a href="/files/2009/08/datasnapisapibrowser_1880.jpg"><img src="/files/2009/08/datasnapisapibrowser_1880.jpg" alt="" width="652" height="243" /></a></p>
<p>The following a wizard generated line of code provide the default content:</p>
<p><a href="/files/2009/08/datasnapisapidefaulthandleraction_1883.jpg"><img src="/files/2009/08/datasnapisapidefaulthandleraction_1883.jpg" alt="" width="658" height="100" /></a> </p>
<p>At this point it looks like our ISAPI dll is properly configured.  Now I can use the Data Explorer to test connectivity.</p>
<p><a name="dataexplorer">Connect with Data Explorer</a></p>
<p>I prefer to use the stand alone DataExplore.exe when testing connections rather than the RAD studio Data Explorer view, just in case there is a connection problem that causes the client to become unresponsive. </p>
<p>Start DataExplorer.exe.  Right click the DataSnap node, choose add connection.  Enter “NewConnection”.  Click OK.</p>
<p><a href="/files/2009/08/datasnapisapiaddnewconnection_1889.jpg&quot;"><img src="/files/2009/08/datasnapisapiaddnewconnection_1889.jpg" alt="" width="243" height="196" /></a></p>
<p>Expand the DataSnap node, right click “New Connection” and select “Modify Connection”.</p>
<p>Set Protocol to “http”, Host to “localhost”, Port to “80” and Path to “DsProject/Project1.dll”.</p>
<p>Click “Test Connection”.   Click OK. Click OK. </p>
<p> </p>
<p><a href="/files/2009/08/datasnapisapimodifyconnection_1886.jpg"><img src="/files/2009/08/datasnapisapimodifyconnection_1886.jpg" alt="" width="472" height="529" /></a></p>
<p>Expand the NewConnection/Procedures node to see that EchoString is a server method.</p>
<p><a href="/files/2009/08/datasnapisapidataexplorerprocedures_1891.jpg"><img src="/files/2009/08/datasnapisapidataexplorerprocedures_1891.jpg" alt="" width="414" height="538" /></a></p>
<p>To test, right click on the “EchoString” node and choose "View Parameters". Select the "Value" parameter and enter some text for the "Value" property. Right click and choose "Execute" (or click the the  image button in the upper left of the view parameters window).  </p>
<p><a href="/files/2009/08/datasnapisapiviewparameters_1897.jpg"><img src="/files/2009/08/datasnapisapiviewparameters_1897.jpg" alt="" width="667" height="425" /></a></p>
<p>At this point I’ve created a server, configured it to run under IIS, and connected to it with DataExplorer.   The new DataSnap 2010 HTTP client features will need to be covered in another post.</p>
<p>I have two additional topics to cover.  First is this ancestor issue I mentioned near the beginning of this post.  Finally, I will add a few words about debugging.</p>
<p><a name="ancestors">Ancestors and DataModules</a></p>
<p>This example used TPersistent as the ancestor of our server method class.   The other choices, in the wizard, are TDataModule and TDSServerModule.  Use TDataModule when you want to use components in your server methods.  Use TDSServerModule when you want the equivalent of TRemoteDataModule.</p>
<p>When using TDataModule or TDSServerModule, there is an important requirement that only affects WebBroker applications.  Be sure that the there is only one module created during startup.  Use Project/View Source… to see this code.  The only module created here should be the WebModule. </p>
<p>The project source should look like this:</p>
<p><a href="/files/2009/08/datasnapisapiviewsource1_1900.jpg"><img src="/files/2009/08/datasnapisapiviewsource1_1900.jpg" alt="" width="498" height="156" /></a></p>
<p>Something like this will result in an exception with the message “Only one data module per application”.</p>
<p><img src="/files/2009/08/datasnapisapiviewsource2_1903.jpg" alt="" width="509" height="168" /></p>
<p><a name="debugging">ISAPI Debugging</a></p>
<p>In case your ISAPI dll isn’t working properly because of this or other issues, here is how I configure my project for debugging.</p>
<p>In project options, set Host application to the location of w3wp.exe and the Parameters to “-debug”.</p>
<p><a href="/files/2009/08/datasnapisapidebugoptions_1906.jpg"><img src="/files/2009/08/datasnapisapidebugoptions_1906.jpg" alt="" width="596" height="412" /></a></p>
<p>You will need to stop IIS before debugging.  Use the IIS manager or [c:/]net stop w3svc.</p>
<p>When you run the application, you should see a prompt like this:</p>
<p>When you stop debugging, w3wp.exe will be shut down.   When you are done working on your project, restore IIS with [c:/]net start w3svc.</p>
<p class="akst_link"><a href="http://blogs.embarcadero.com/jimtierney/?p=31502&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_31502" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=DataSnap%202010%20HTTP%20support%20with%20an%20ISAPI%20dll&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fjimtierney%2F2009%2F08%2F20%2F31502" id="akst_email_31502" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/jimtierney/2009/08/20/31502/feed</wfw:commentRss>
		</item>
		<item>
		<title>Delphi Prism and DataSnap Server Method Stream Parameters</title>
		<link>http://blogs.embarcadero.com/jimtierney/2009/04/25/31487</link>
		<comments>http://blogs.embarcadero.com/jimtierney/2009/04/25/31487#comments</comments>
		<pubDate>Sat, 25 Apr 2009 12:25:57 +0000</pubDate>
		<dc:creator>Jim Tierney</dc:creator>
		
		<category><![CDATA[DataSnap]]></category>

		<category><![CDATA[Delphi Prism]]></category>

		<category><![CDATA[Oxygene]]></category>

		<category><![CDATA[ADO.NET]]></category>

		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[Generics]]></category>

		<category><![CDATA[Prism]]></category>

		<category><![CDATA[Server Methods]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/jimtierney/?p=31487</guid>
		<description><![CDATA[This post is about using Delphi Prism to pass streams to/from DataSnap server methods.&#160; The sample client that goes along with this post is available here: http://cc.embarcadero.com/item/26874. 
This client has the same functionality as the Delphi client described in this post: DataSnap Server Method Stream Parameters.&#160; Here is a screen shot of the two clients [...]]]></description>
			<content:encoded><![CDATA[<p>This post is about using Delphi Prism to pass streams to/from DataSnap server methods.&nbsp; The sample client that goes along with this post is available here: <a href="http://cc.embarcadero.com/item/26874">http://cc.embarcadero.com/item/26874</a>. </p>
<p>This client has the same functionality as the Delphi client described in this post: <a href="http://blogs.embarcadero.com/jimtierney/2009/04/06/31461">DataSnap Server Method Stream Parameters</a>.&nbsp; Here is a screen shot of the two clients running against the same Delphi sample server.</p>
<p><a href="/files/2009/04/streamsclient_1203.jpg"><img alt="" src="/files/2009/04/streamsclient_1203.jpg"></a></p>
<p>Download the Delphi sample server (and Delphi sample client) here: <a href="http://cc.codegear.com/item/26854">http://cc.codegear.com/item/26854.</a>&nbsp;&nbsp; For introductory information about the difference between Delphi and Delphi Prism DataSnap clients see this post: <a href="http://blogs.embarcadero.com/jimtierney/2009/03/25/31442">Call DataSnap Server Methods with Delphi Prism</a>.</p>
<h4>Stream Parameter Types</h4>
<p>This table shows the parameter types and return types in the stream samples. The columns under “Server Parameter” describe the parameter or return type in the Delphi DataSnap servers methods. The “Delphi Type” column shows the corresponding type used in the Delphi client. The “Delphi Prism Type” column shows type used in the Delphi Prism client.</p>
<table border="1">
<tbody>
<tr>
<th colspan="5">Server Parameter</th>
<th colspan="2">Client Parameters</th>
</tr>
<tr>
<th>Type</th>
<th>(default)</th>
<th>var</th>
<th>out</th>
<th>Result</th>
<th>Delphi Type</th>
<th>Delphi Prism Type</th>
</tr>
<tr>
<td>TStream</td>
<td>
<p align="center"><img src="/files/2009/04/checkmark_1202.jpg">(in)</p>
</td>
<td>
<p align="center"><img src="/files/2009/04/checkmark_1202.jpg"></p>
</td>
<td>
<p align="center"><img src="/files/2009/04/checkmark_1202.jpg"></p>
</td>
<td>
<p align="center"><img src="/files/2009/04/checkmark_1202.jpg"></p>
</td>
<td>TStream</td>
<td>System.IO.Stream</td>
</tr>
<tr>
<td>TDBXStreamValue</td>
<td>
<p align="center"><img src="/files/2009/04/checkmark_1202.jpg">(in/out) </p>
</td>
<td>
<p align="center">&nbsp;</p>
</td>
<td>
<p align="center">&nbsp;</p>
</td>
<td>
<p align="center">&nbsp;</p>
</td>
<td>TStream</td>
<td>System.IO.Stream</td>
</tr>
</tbody>
</table>
<p></p>
<h4>Code Samples</h4>
<p>The following code samples show the differences between calling server methods with DbExpress in Delphi compared to ADO.NET in Delphi Prism.</p>
<table border="1">
<tbody>
<tr>
<th>TStream Server Method</th>
</tr>
<tr>
<td>
<pre>function TTestStream.Echo(I: TStream): TStream;
</pre>
</td>
</tr>
<tr>
<th>Delphi/DbExpress</th>
</tr>
<tr>
<td>
<pre>function TTestStreamClient.Echo(I: TStream): TStream;
begin
  if FEchoCommand = nil then
  begin
    FEchoCommand := FDBXConnection.CreateCommand;
    FEchoCommand.CommandType := TDBXCommandTypes.DSServerMethod;
    FEchoCommand.Text := 'TTestStream.Echo';
    FEchoCommand.Prepare;
  end;
  FEchoCommand.Parameters[0].Value.SetStream(I, FInstanceOwner);
  FEchoCommand.ExecuteUpdate;
  Result := FEchoCommand.Parameters[1].Value.GetStream(FInstanceOwner);
end;
</pre>
</td>
</tr>
<tr>
<th>Delphi Prism/ADO.NET </th>
</tr>
<tr>
<td>
<pre>function TTestStreamClient.Echo(I: System.IO.Stream): System.IO.Stream;
begin
  if FEchoCommand = nil then
  begin
    FEchoCommand := FDBXConnection.CreateCommand as TAdoDbxCommand;
    FEchoCommand.CommandType := System.Data.CommandType.StoredProcedure;
    FEchoCommand.CommandText := 'TTestStream.Echo';
    FEchoCommand.Prepare;
  end;
  FEchoCommand.Parameters[0].Value := I;
  FEchoCommand.ExecuteNonQuery;
  Result := FEchoCommand.Parameters[1].Value as System.IO.Stream;
end;
</pre>
</td>
</tr>
</tbody>
</table>
<p></p>
<table border="1">
<tbody>
<tr>
<th>TDBXStreamValue Server Method</th>
</tr>
<tr>
<td>
<pre>procedure TTestStreamValue.Swap(I: TDBXStreamValue; J: TDBXStreamValue);
</pre>
</td>
<tr>
<th>Delphi/DbExpress</th>
</tr>
<tr>
<td>
<pre>procedure TTestStreamValueClient.Swap(var I: TStream; var J: TStream);
begin
  if FSwapCommand = nil then
  begin
    FSwapCommand := FDBXConnection.CreateCommand;
    FSwapCommand.CommandType := TDBXCommandTypes.DSServerMethod;
    FSwapCommand.Text := 'TTestStreamValue.Swap';
    FSwapCommand.Prepare;
  end;
  if I = nil then
    FSwapCommand.Parameters[0].Value.SetNull
  else
    FSwapCommand.Parameters[0].Value.SetStream(I, FInstanceOwner);
  if J = nil then
    FSwapCommand.Parameters[1].Value.SetNull
  else
    FSwapCommand.Parameters[1].Value.SetStream(J,  FInstanceOwner);
  FSwapCommand.ExecuteUpdate;
  if FSwapCommand.Parameters[0].Value.IsNull then
    I := nil
  else
    I := FSwapCommand.Parameters[0].Value.GetStream(FInstanceOwner);
  if FSwapCommand.Parameters[1].Value.IsNull then
    J := nil
  else
    J := FSwapCommand.Parameters[1].Value.GetStream(FInstanceOwner);
end;
</pre>
</td>
</tr>
<tr>
<th>Delphi Prism/ADO.NET </th>
</tr>
<tr>
<td>
<pre>procedure TTestStreamValueClient.Swap(var I: System.IO.Stream; var J: System.IO.Stream);
begin
  if FSwapCommand = nil then
  begin
    FSwapCommand := FDBXConnection.CreateCommand as TAdoDbxCommand;
    FSwapCommand.CommandType := System.Data.CommandType.StoredProcedure;
    FSwapCommand.CommandText := 'TTestStreamValue.Swap';
    FSwapCommand.Prepare;
  end;
  if I = nil then
    FSwapCommand.Parameters[0].Value := DbNull.Value
  else
    FSwapCommand.Parameters[0].Value := I;
  if J = nil then
    FSwapCommand.Parameters[1].Value := DbNull.Value
  else
    FSwapCommand.Parameters[1].Value := J;
  FSwapCommand.ExecuteNonQuery;
  if FSwapCommand.Parameters[0].Value = DBNull.Value then
    I := nil
  else
    I := FSwapCommand.Parameters[0].Value as System.IO.Stream;
  if FSwapCommand.Parameters[1].Value = DBNull.Value then
    J := nil
  else
    J := FSwapCommand.Parameters[1].Value as System.IO.Stream;
end;
</pre>
</td>
</tr>
</tbody>
</table>
<p>That’s all for now.&nbsp; A post on table parameter types is coming soon.&nbsp;</p>
<p class="akst_link"><a href="http://blogs.embarcadero.com/jimtierney/?p=31487&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_31487" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Delphi%20Prism%20and%20DataSnap%20Server%20Method%20Stream%20Parameters&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fjimtierney%2F2009%2F04%2F25%2F31487" id="akst_email_31487" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/jimtierney/2009/04/25/31487/feed</wfw:commentRss>
		</item>
		<item>
		<title>DataSnap Server Method Stream Parameters</title>
		<link>http://blogs.embarcadero.com/jimtierney/2009/04/06/31461</link>
		<comments>http://blogs.embarcadero.com/jimtierney/2009/04/06/31461#comments</comments>
		<pubDate>Mon, 06 Apr 2009 19:11:19 +0000</pubDate>
		<dc:creator>Jim Tierney</dc:creator>
		
		<category><![CDATA[DataSnap]]></category>

		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[Generics]]></category>

		<category><![CDATA[Server Methods]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/jimtierney/?p=31461</guid>
		<description><![CDATA[This is a continuation of my posts on DataSnap server method parameters and return types.  This post is about  TStream and TDBXStreamValue.    The sample client and server projects that go with this post can be downloaded here: http://cc.embarcadero.com/item/26854
See my earlier posts on “Basic” and “Basic DBXValue” types.   I’ve yet to post about TDBXConnection, TDBXConnectionValue, TDBXReader, [...]]]></description>
			<content:encoded><![CDATA[<p>This is a continuation of my posts on DataSnap server method parameters and return types.  This post is about  TStream and TDBXStreamValue.    The sample client and server projects that go with this post can be downloaded here: <a href="http://cc.embarcadero.com/item/26854">http://cc.embarcadero.com/item/26854</a></p>
<p>See my earlier posts on “Basic” and “Basic DBXValue” types.   I’ve yet to post about TDBXConnection, TDBXConnectionValue, TDBXReader, TParams, and TDataSet.  However, TDataSet is demonstrated in the sample projects.</p>
<table border="0">
<tbody>
<tr>
<th>Basic</th>
<th>Basic DBXValue</th>
<th>Collection</th>
<th>Connection</th>
</tr>
<tr>
<td valign="top">
<ul>
<li>AnsiString</li>
<li>Boolean</li>
<li>Currency</li>
<li>TDateTime</li>
<li>TDBXDate</li>
<li>TDBXTime</li>
<li>Double</li>
<li>Int64</li>
<li>Integer</li>
<li>LongInt</li>
<li>OleVariant</li>
<li>Single</li>
<li>SmallInt</li>
<li>WideString</li>
</ul>
</td>
<td valign="top">
<ul>
<li>TDBXAnsiStringValue</li>
<li>TDBXAnsiCharsValue</li>
<li>TDBXBcdValue</li>
<li>TDBXBooleanValue</li>
<li>TDBXDateValue</li>
<li>TDBXDoubleValue</li>
<li>TDBXInt16Value</li>
<li>TDBXInt32Value</li>
<li>TDBXInt64Value</li>
<li>TDBXSingleValue</li>
<li>TDBXStringValue</li>
<li>TDBXTimeStampValue</li>
<li>TDBXTimeValue</li>
<li>TDBXWideCharsValue</li>
<li>TDBXWideStringValue</li>
</ul>
</td>
<td valign="top">
<table border="0">
<tbody>
<tr>
<td>
<ul>
<li>TDBXReader</li>
<li>TDataSet</li>
<li>TParams</li>
<li>TStream</li>
</ul>
</td>
</tr>
<tr>
<td>
<table border="0">
<tbody>
<tr>
<th>Collection DBXValue</th>
</tr>
<tr>
<td>
<ul>
<li>TDBXReaderValue</li>
<li>TDBXStreamValue</li>
</ul>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
<td valign="top">
<table border="0">
<tbody>
<tr>
<td>
<ul>
<li>TDBXConnection</li>
</ul>
</td>
</tr>
<tr>
<td>
<table border="0">
<tbody>
<tr>
<th>Connection DBXValue</th>
</tr>
<tr>
<td>
<ul>
<li>TDBXConnectionValue</li>
</ul>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<p>The following table summarizes differences between TStream and TDBXStreamValue types:</p>
<table border="1" cellpadding="4">
<tbody>
<tr>
<td rowspan="2"> </td>
<th rowspan="2">Supports null values</th>
<th colspan="3">Declaration</th>
<th colspan="2">Accessing Values</th>
<th rowspan="2">Proxy generator</th>
</tr>
<tr>
<th>Default parameter direction</th>
<th>Other parameter directions</th>
<th>function result type</th>
<th>Get</th>
<th>Set</th>
</tr>
<tr>
<th>TStream</th>
<td align="center">No</td>
<td>
<p align="center"><span>in</span></p>
</td>
<td>
<p align="center">in/out: use <em>var</em> keyword out: use <em>out</em> keyword</p>
</td>
<td>
<p align="center"><span>Yes</span></p>
</td>
<td>lhs := AParameter</td>
<td>AParameter := rhs</td>
<td>
<p align="center"><span>Yes </span></p>
</td>
</tr>
<tr>
<th>TDBXStreamValue</th>
<td>
<p align="center">Yes</p>
</td>
<td>
<p align="center">in/out</p>
</td>
<td>
<p align="center">None</p>
</td>
<td>
<p align="center">No</p>
</td>
<td>AParameter.IsNull lhs:=AParameter.GetStream(InstanceOwner)</td>
<td>AParameter.SetNull AParameter.SetStream(rhs, InstanceOwner)</td>
<td>
<p align="center">No</p>
</td>
</tr>
</tbody>
</table>
<h4>Supports null values</h4>
<p>The TDBXStreamValue type has an IsNull property and a SetNull method.   Use this type instead of TStream a parameter value can be null/nil, in some cases.</p>
<h4>Declaration</h4>
<p>The <em>var</em> and <em>out</em> keywords can’t be used to specify the parameter direction of a TDBXStreamValue parameter.  The direction is always in/out. A TDBXStreamValue type can’t be used as a function result.</p>
<h4>Proxy Generator</h4>
<p>The RAD Studio 2007 client proxy generator does not work properly for server methods with TDBXStreamValue parameters. So you will need to hand code the client code or correct the generated proxy. The sample client has hand corrected proxy methods that look like this.</p>
<pre>function TTestStreamValueClient.Echo(var I: TStream): TStream;
begin
  if FEchoCommand = nil then
  begin
    FEchoCommand := FDBXConnection.CreateCommand;
    FEchoCommand.CommandType := TDBXCommandTypes.DSServerMethod;
    FEchoCommand.Text := 'TTestStreamValue.Echo';
    FEchoCommand.Prepare;
  end;
  if I = nil then
    FEchoCommand.Parameters[0].Value.SetNull
  else
    FEchoCommand.Parameters[0].Value.SetStream(I, FInstanceOwner);
  FEchoCommand.ExecuteUpdate;
  if FEchoCommand.Parameters[0].Value.IsNull then
    I := nil
  else
    I := FEchoCommand.Parameters[0].Value.GetStream(FInstanceOwner);
  Result := FEchoCommand.Parameters[1].Value.GetStream(FInstanceOwner);
end;</pre>
<p>This client method works with a server method declared as follows:</p>
<pre>function Echo(I: TDBXStreamValue): TStream;</pre>
<p>Calling a server method with a TDBXStreamValue parameter is the same as calling a server method with an TStream parameter, except that you can use SetNull and IsNull methods to work with null values.</p>
<p>For example, compare the following server method declaration and client method implementation to the previous example:</p>
<pre>function Echo(I: TStream): TStream; </pre>
<pre>function TTestStreamClient.Echo(I: TStream): TStream;
begin
  if FEchoCommand = nil then
  begin
    FEchoCommand := FDBXConnection.CreateCommand;
    FEchoCommand.CommandType := TDBXCommandTypes.DSServerMethod;
    FEchoCommand.Text := 'TTestStream.Echo';
    FEchoCommand.Prepare;
  end;
  FEchoCommand.Parameters[0].Value.SetStream(I, FInstanceOwner);
  FEchoCommand.ExecuteUpdate;
  Result := FEchoCommand.Parameters[1].Value.GetStream(FInstanceOwner);
end;</pre>
<h4>Accessing Values</h4>
<p>The GetStream and SetStream methods have an InstanceOwner parameter.  Passing True indicates that DBX owns the stream and will free it.  Passing False indicates that the caller owns the stream.  To control how the generated proxy classes call SetStream and GetStream, there is an AInstanceOwner parameter on the proxy class constructor:</p>
<pre>constructor TTestStreamClient.Create(ADBXConnection: TDBXConnection; AInstanceOwner: Boolean);</pre>
<p>The other constructor is equivalent to passing AInstanceOwner as True.</p>
<pre>constructor TTestStreamClient.Create(ADBXConnection: TDBXConnection);</pre>
<p> </p>
<h4>Sample Client And Server Applications</h4>
<p>The sample server has a few simple server methods for passing values (including null).</p>
<pre>  {$METHODINFO ON}
  TTestCollection = class(TComponent)
  strict protected
    procedure LogMessage(const AMessage: string);
  public
    // Server method to get the parameter type names
    procedure GetTypeNames(I: T; ADeclaredName, AActualName: TDBXStringValue);
  end;
  {$METHODINFO OFF}

  TTestStream = class(TTestCollection)
  public
    function Echo(I: TStream): TStream;
    procedure Copy(I: TStream; out J: TStream);
    procedure Swap(var I: TStream; var J: TStream);
  end;

  TTestStreamValue = class(TTestCollection)
  public
    function Echo(I: TDBXStreamValue): TStream;
    procedure Copy(I: TDBXStreamValue; J: TDBXStreamValue);
    procedure Swap(I: TDBXStreamValue; J: TDBXStreamValue);
    function IsNull(I: TDBXStreamValue): Boolean;
    procedure SetNull(I: TDBXStreamValue);
  end;</pre>
<p>The sample client tests the server methods by calling them with sample values and verifying the results (e.g; comparing streams). TMemoryStream is used to pass short streams and TFileStream to pass long streams.  Here is a screen shot of the running server and client:</p>
<p><a href="/files/2009/04/streamsserverclient_1154.jpg"><img src="/files/2009/04/streamsserverclient_1154.jpg" alt="" width="614" height="433" /></a></p>
<p>The following table shows the parameter types and return types demonstrated in the sample client and server:</p>
<table border="1" cellpadding="4">
<tbody>
<tr>
<th rowspan="2">Type</th>
<th colspan="4">Direction</th>
</tr>
<tr>
<th>(default)</th>
<th>var</th>
<th>out</th>
<th>Result</th>
</tr>
<tr>
<td>TDBXStreamValue</td>
<td>X (in/out)</td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td>TStream</td>
<td>X (in)</td>
<td>X</td>
<td>X</td>
<td>X</td>
</tr>
</tbody>
</table>
<p> </p>
<h4>Stream Usage</h4>
<p>Check  “Log Stream Usage” to show TStream sizes, type names, creates, destroys, and reads.  The results from 4 different test cases are displayed after “Call Server Methods” is clicked. </p>
<p>The screen shot below shows the result from a test case with longer streams.  I’ve added highlighting to illustrate these points:</p>
<ol>
<li>When the server reads a longer stream passed from the client, round trips are made to the client.  This makes it possible to send very large streams to the server without consuming lots of memory.</li>
<li>When the client reads a longer stream passed from the server, round trips are made to the server.  This makes it possible to return very large streams to the client without consuming lots of memory.</li>
<li>The TStream objects that represent longer client and server streams have a Size of –1, meaning the size is unknown.  Rely on the return value of TStream.Read to detect the end of the stream.  Also note that some DBX streams such as TDBXStreamReaderStream do not fully support Seek.</li>
</ol>
<p><a href="/files/2009/04/streamusage_1157.jpg"><img src="/files/2009/04/streamusage_1157.jpg" alt="" width="438" height="669" /></a></p>
<p>That’s all for now.</p>
<p class="akst_link"><a href="http://blogs.embarcadero.com/jimtierney/?p=31461&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_31461" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=DataSnap%20Server%20Method%20Stream%20Parameters&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fjimtierney%2F2009%2F04%2F06%2F31461" id="akst_email_31461" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/jimtierney/2009/04/06/31461/feed</wfw:commentRss>
		</item>
		<item>
		<title>Call DataSnap Server Methods with Delphi Prism</title>
		<link>http://blogs.embarcadero.com/jimtierney/2009/03/25/31442</link>
		<comments>http://blogs.embarcadero.com/jimtierney/2009/03/25/31442#comments</comments>
		<pubDate>Wed, 25 Mar 2009 15:39:30 +0000</pubDate>
		<dc:creator>Jim Tierney</dc:creator>
		
		<category><![CDATA[DataSnap]]></category>

		<category><![CDATA[Delphi Prism]]></category>

		<category><![CDATA[Oxygene]]></category>

		<category><![CDATA[ADO.NET]]></category>

		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[Generics]]></category>

		<category><![CDATA[Prism]]></category>

		<category><![CDATA[Server Methods]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/jimtierney/?p=31442</guid>
		<description><![CDATA[This post provides information about calling DataSnap server methods from Delphi Prism clients.
There are two new samples that go along with this post: http://cc.embarcadero.com/item/26806 and http://cc.embarcadero.com/item/26805
The first sample is a Delphi Prism client that demonstrates "Basic" types.&#160; This client has nearly the same functionality as the Delphi client described in this post: DataSnap Server Methods [...]]]></description>
			<content:encoded><![CDATA[<p>This post provides information about calling DataSnap server methods from Delphi Prism clients.</p>
<p>There are two new samples that go along with this post: <a href="http://cc.embarcadero.com/item/26806">http://cc.embarcadero.com/item/26806</a> and <a href="http://cc.embarcadero.com/item/26805">http://cc.embarcadero.com/item/26805</a></p>
<p>The first sample is a Delphi Prism client that demonstrates "Basic" types.&nbsp; This client has nearly the same functionality as the Delphi client described in this post: <a href="http://blogs.embarcadero.com/jimtierney/2009/02/13/31362">DataSnap Server Methods Parameters</a>.&nbsp; The difference is that the Delphi Prism client isn’t able to call server methods with OleVariant parameter types.&nbsp; The Delphi client is shown on the left and the Delphi Prism client on the right:</p>
<p><a href="/files/2009/03/delphiandprismbasicclients_1121.jpg"><img alt="" src="/files/2009/03/delphiandprismbasicclients_1121.jpg"></a> </p>
<p>The second sample is a Delphi Prism client that demonstrates "Basic DBXValue" types.&nbsp; This client has the same functionality as the Delphi client described in this post: <a href="http://blogs.embarcadero.com/jimtierney/2009/03/12/31407">DataSnap Server Method DBXValue Parameters</a>.&nbsp; The Delphi client is shown on the left and the Delphi Prism client on the right:</p>
<p><a href="/files/2009/03/delphiandprismbasicdbxvalueclients_1115.jpg"><img alt="" src="/files/2009/03/delphiandprismbasicdbxvalueclients_1115.jpg"></a> </p>
<p>The Delphi Prism clients use the same sample servers as the Delphi clients.&nbsp; Download the Delphi sample servers (and Delphi sample clients) here: <a href="http://cc.codegear.com/item/26702">http://cc.codegear.com/item/26702</a>, <a href="http://cc.embarcadero.com/item/26734">http://cc.embarcadero.com/item/26734</a>.</p>
<p>The following table summarizes the major differences between the Delphi and Delphi Prism sample clients:</p>
<table width="511" border="1">
<tbody>
<tr>
<th rowspan="2">Clients</th>
<th colspan="2">Connectivity</th>
<th rowspan="2">Proxy Generator</th>
<th rowspan="2">UI Framework</th>
<th rowspan="2">Parameter Types</th>
<th rowspan="2">Language/RTL</th>
</tr>
<tr>
<th>Framework</th>
<th>Types</th>
</tr>
<tr>
<th>Delphi </th>
<td>DbExpress</td>
<td>
<p align="center">TDBXConnection, TDBXCommand</p>
</td>
<td>
<p align="center">Yes</p>
</td>
<td>
<p align="center">VCL</p>
</td>
<td>
<p align="center">Delphi </p>
</td>
<td>Delphi/Delphi</td>
</tr>
<tr>
<th>Delphi Prism </th>
<td>ADO.NET</td>
<td>
<p align="center">TAdoDbxConnection, TAdoDbxCommand</p>
</td>
<td>
<p align="center">No</p>
</td>
<td>
<p align="center">WinForms</p>
</td>
<td>
<p align="center">Oxygene/.NET </p>
</td>
<td>Oxygene/.NET</td>
</tr>
</tbody>
</table>
<p></p>
<h4>Connectivity </h4>
<p>The Delphi Prism client uses the DataSnap ADO.NET provider rather than native DbExpress.&nbsp; Here are some code samples to show differences between calling DataSnap server methods with DbExpress in Delphi vs. ADO.NET in Delphi Prism.</p>
<table border="1">
<tbody>
<tr>
<th>Delphi</th>
</tr>
<tr>
<td>
<pre>  TTestIntegerClient = class
  private
    FDBXConnection: TDBXConnection;
    FInstanceOwner: Boolean;
    FEchoCommand: TDBXCommand;
    FCopyCommand: TDBXCommand;
    FSwapCommand: TDBXCommand;
  public
    constructor Create(ADBXConnection: TDBXConnection); overload;
    constructor Create(ADBXConnection: TDBXConnection; AInstanceOwner: Boolean); overload;
    destructor Destroy; override;
    function Echo(I: Integer): Integer;
    procedure Copy(I: Integer; out J: Integer);
    procedure Swap(var I: Integer; var J: Integer);
  end;
</pre>
</td>
</tr>
<tr>
<th>Delphi Prism</th>
</tr>
<tr>
<td>
<pre>  TTestIntegerClient = class
  private
    FDBXConnection: TAdoDbxConnection;
    FInstanceOwner: Boolean;
    FEchoCommand: TAdoDbxCommand;
    FCopyCommand: TAdoDbxCommand;
    FSwapCommand: TAdoDbxCommand;
  protected
    procedure Dispose(ADisposing: Boolean); virtual;
  public
    constructor Create(ADBXConnection: TAdoDbxConnection);
    constructor Create(ADBXConnection: TAdoDbxConnection; AInstanceOwner: Boolean);
    procedure Dispose; virtual;
    function Echo(I: Integer): Integer;
    procedure Copy(I: Integer; out J: Integer);
    procedure Swap(var I: Integer; var J: Integer);
  end;
<pre></pre>
</pre>
</td>
</tr>
<tr>
<th>Delphi</th>
</tr>
<tr>
<td>
<pre>procedure TTestIntegerClient.Swap(var I: Integer; var J: Integer);
begin
  if FSwapCommand = nil then
  begin
    FSwapCommand := FDBXConnection.CreateCommand;
    FSwapCommand.CommandType := TDBXCommandTypes.DSServerMethod;
    FSwapCommand.Text := 'TTestInteger.Swap';
    FSwapCommand.Prepare;
  end;
  FSwapCommand.Parameters[0].Value.SetInt32(I);
  FSwapCommand.Parameters[1].Value.SetInt32(J);
  FSwapCommand.ExecuteUpdate;
  I := FSwapCommand.Parameters[0].Value.GetInt32;
  J := FSwapCommand.Parameters[1].Value.GetInt32;
end;
</pre>
</td>
</tr>
<tr>
<th>Delphi Prism</th>
</tr>
<tr>
<td>
<pre>procedure TTestIntegerClient.Swap(var I: Integer; var J: Integer);
begin
  if FSwapCommand = nil then
  begin
    FSwapCommand := FDBXConnection.CreateCommand as TAdoDbxCommand;
    FSwapCommand.CommandType := System.Data.CommandType.StoredProcedure;
    FSwapCommand.CommandText := 'TTestInteger.Swap';
    FSwapCommand.Prepare;
  end;
  FSwapCommand.Parameters[0].Value := I;
  FSwapCommand.Parameters[1].Value := J;
  FSwapCommand.ExecuteNonQuery;
  I := FSwapCommand.Parameters[0].Value as Integer;
  J := FSwapCommand.Parameters[1].Value as Integer;
end;
</pre>
</td>
</tr>
</tbody>
</table>
<p></p>
<h4>Proxy Generator</h4>
<p>Delphi Prism does not have a DataSnap client proxy generator like the one in Delphi.&nbsp; The preceding Delphi code sample was generated with the proxy generator; the Delphi Prism code sample was hand written.</p>
<h4>UI Framework </h4>
<p>The Delphi Prism sample clients are WinForm applications.&nbsp; DataSnap clients may be implemented in other application types supported by Delphi Prism, such as ASP.NET.&nbsp; </p>
<h4>Parameter Types</h4>
<p>The following table shows the parameter types and return types demonstrated in the “Basic” types samples.&nbsp;&nbsp; The columns under “Server Parameter” describe the parameter or return type in the Delphi DataSnap server’s methods.&nbsp; The “Delphi Type” column shows the corresponding type used in the Delphi client.&nbsp; The “Delphi Prism Type” show the corresponding type used in the Delphi Prism client. </p>
<table width="276" border="1">
<tbody>
<tr>
<th colspan="5">Server Parameter</th>
<th colspan="2">Client Parameters</th>
<tr>
<tr>
<th>Type</th>
<th>(in)</th>
<th>var</th>
<th>out</th>
<th>Result</th>
<th>Delphi Type</th>
<th>Delphi&nbsp;Prism Type</th>
<tr>
<td>AnsiString</td>
<td>X</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>X</td>
<td>AnsiString</td>
<td>String</td>
</tr>
<tr>
<td>Boolean</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>Boolean</td>
<td>Boolean</td>
</tr>
<tr>
<td>Currency</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>Currency</td>
<td>Decimal</td>
</tr>
<tr>
<td>TDateTime</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>TDateTime</td>
<td>DateTime</td>
</tr>
<tr>
<td>TDBXDate</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>TDBXDate</td>
<td>DateTime</td>
</tr>
<tr>
<td>TDBXTime</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>TDBXTime</td>
<td>DateTime</td>
</tr>
<tr>
<td>Double</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>Double</td>
<td>Double</td>
</tr>
<tr>
<td>Int64</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>Int64</td>
<td>Int64</td>
</tr>
<tr>
<td>Integer</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>Integer</td>
<td>Integer</td>
</tr>
<tr>
<td>LongInt</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>LongInt</td>
<td>LongInt</td>
</tr>
<tr>
<td>OleVariant</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>&nbsp;</td>
<td>OleVariant</td>
<td>&lt;Not supported&gt;</td>
</tr>
<tr>
<td>Single</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>Single</td>
<td>Single</td>
</tr>
<tr>
<td>SmallInt</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>SmallInt</td>
<td>SmallInt</td>
</tr>
<tr>
<td>String</td>
<td>X</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>X</td>
<td>String</td>
<td>String</td>
</tr>
<tr>
<td>WideString</td>
<td>X</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>X</td>
<td>WideString</td>
<td>String</td>
</tr>
</tbody>
</table>
<p></p>
<p>The following table shows the parameter types and return types demonstrated in the “Basic DBXValue” types samples:</p>
<table cellpadding="4" width="388" border="1">
<tbody>
<tr>
<th colspan="5">Server Parameter</th>
<th colspan="2">Client Parameters</th>
<tr>
<tr>
<tr>
<th>Type</th>
<th>(in/out)</th>
<th>var</th>
<th>out</th>
<th>Result</th>
<th>Delphi Type</th>
<th>Delphi&nbsp;Prism Type</th>
</tr>
<tr>
<td>TDBXAnsiCharsValue</td>
<td>X</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>AnsiString</td>
<td>string</td>
</tr>
<tr>
<td>TDBXAnsiStringValue</td>
<td>X</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>AnsiString</td>
<td>string</td>
</tr>
<tr>
<td>TDBXBcdValue</td>
<td>X</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>TBcd</td>
<td>Decimal</td>
</tr>
<tr>
<td>TDBXBooleanValue</td>
<td>X</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>Boolean</td>
<td>Boolean</td>
</tr>
<tr>
<td>TDBXDateValue</td>
<td>X</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>TDBXDate</td>
<td>DateTime</td>
</tr>
<tr>
<td>TDBXDoubleValue</td>
<td>X</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>Double</td>
<td>Double</td>
</tr>
<tr>
<td>TDBXInt16Value</td>
<td>X</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>Int16</td>
<td>Int16</td>
</tr>
<tr>
<td>TDBXInt32Value</td>
<td>X</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>Int32</td>
<td>Int32</td>
</tr>
<tr>
<td>TDBXInt64Value</td>
<td>X</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>Int64</td>
<td>Int64</td>
</tr>
<tr>
<td>TDBXSingleValue</td>
<td>X</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>Single</td>
<td>Single</td>
</tr>
<tr>
<td>TDBXStringValue</td>
<td>X</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>String</td>
<td>String</td>
</tr>
<tr>
<td>TDBXTimeValue</td>
<td>X</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>TDBXTime</td>
<td>DateTime</td>
</tr>
<tr>
<td>TDBXTimeStampValue</td>
<td>X</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>TSQLTimeStamp</td>
<td>DateTime</td>
</tr>
<tr>
<td>TDBXWideCharsValue</td>
<td>X</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>UnicodeString</td>
<td>string</td>
</tr>
<tr>
<td>TDBXWideStringValue</td>
<td>X</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>&nbsp;</td>
<td>UnicodeString</td>
<td>string</td>
</tr>
</tbody>
</table>
<p></p>
<h4>Language Compatability</h4>
<h5>Syntax</h5>
<p>Delphi Prism projects uses the Oxygene language.</p>
<p>In these samples, there are a few syntax differences between Oxygene .pas files and Delphi .pas files including&nbsp; keyword (e.g.; unit vs. namespace, var and out in method calls) and a delimiter (e.g.; Oxygene requires&nbsp; ‘;’ and <a href="mailto:&lsquo;@&rsquo;">‘@’</a> in places that Delphi doesn’t).&nbsp; Diff the like named .pas files for details.</p>
<p>Delphi Prism has some project options that enable the Oxygene compiler to accept more Delphi language conventions.&nbsp; Choose “Project/Project properties…”&nbsp; The one I’ve checked for these samples is “Allow ‘Create’ constructor calls’.&nbsp; This option enables compilation of the following line: </p>
<p>LTest := TTestBooleanClient.Create(DBXConnection) </p>
<p>Otherwise, the code would need new instead of Create:</p>
<p>LTest := new TTestBooleanClient.(DBXConnection).</p>
<h5>Destroy vs. Dispose</h5>
<p>In the Delphi Prism samples, Dispose is called in place of Destroy in the Delphi samples.&nbsp;&nbsp; Calling Dispose doesn’t free the object but tells the object to release unmanaged resources (like a tcp/ip connection).&nbsp; </p>
<h5>SysUtils.Format vs. String.Format</h5>
<p>In the Delphi Prism samples, String.Format is called in place of Format in the Delphi samples: </p>
<p>LogTestMessage(string.Format(&#8217;{0:s} {1:s}&#8217;, [FClassName + '.' + LMethodName, LDeclaredType])); </p>
<p>in place of</p>
<p>LogTestMessage(Format(&#8217;%0:s (%1:s)&#8217;, [FClassName + '.' + LMethodName, LDeclaredType])); </p>
<p>&nbsp;</p>
<p>That’s all for now.&nbsp; I (continue to) plan on covering collection types in my next post.</p>
<p class="akst_link"><a href="http://blogs.embarcadero.com/jimtierney/?p=31442&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_31442" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=Call%20DataSnap%20Server%20Methods%20with%20Delphi%20Prism&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fjimtierney%2F2009%2F03%2F25%2F31442" id="akst_email_31442" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/jimtierney/2009/03/25/31442/feed</wfw:commentRss>
		</item>
		<item>
		<title>DataSnap Server Method DBXValue Parameters</title>
		<link>http://blogs.embarcadero.com/jimtierney/2009/03/12/31407</link>
		<comments>http://blogs.embarcadero.com/jimtierney/2009/03/12/31407#comments</comments>
		<pubDate>Fri, 13 Mar 2009 02:03:11 +0000</pubDate>
		<dc:creator>Jim Tierney</dc:creator>
		
		<category><![CDATA[DataSnap]]></category>

		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[Generics]]></category>

		<category><![CDATA[Server Methods]]></category>

		<guid isPermaLink="false">http://blogs.embarcadero.com/jimtierney/?p=31407</guid>
		<description><![CDATA[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 [...]]]></description>
			<content:encoded><![CDATA[<p>This post provides more information about DataSnap server method parameters and return types. This is my second post on this subject, following <a href="http://blogs.embarcadero.com/jimtierney/2009/02/13/31362">DataSnap Server Method Parameters</a>. 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: <a href="http://cc.embarcadero.com/item/26734">http://cc.embarcadero.com/item/26734</a></p>
<table border="0">
<tbody>
<tr>
<th>Basic</th>
<th>Basic DBXValue</th>
<th>Collection</th>
<th>Connection</th>
</tr>
<tr>
<td valign="top">
<ul>
<li>AnsiString</li>
<li>Boolean</li>
<li>Currency</li>
<li>TDateTime</li>
<li>TDBXDate</li>
<li>TDBXTime</li>
<li>Double</li>
<li>Int64</li>
<li>Integer</li>
<li>LongInt</li>
<li>OleVariant</li>
<li>Single</li>
<li>SmallInt</li>
<li>WideString</li>
</ul>
</td>
<td valign="top">
<ul>
<li>TDBXAnsiStringValue</li>
<li>TDBXAnsiCharsValue</li>
<li>TDBXBcdValue</li>
<li>TDBXBooleanValue</li>
<li>TDBXDateValue</li>
<li>TDBXDoubleValue</li>
<li>TDBXInt16Value</li>
<li>TDBXInt32Value</li>
<li>TDBXInt64Value</li>
<li>TDBXSingleValue</li>
<li>TDBXStringValue</li>
<li>TDBXTimeStampValue</li>
<li>TDBXTimeValue</li>
<li>TDBXWideCharsValue</li>
<li>TDBXWideStringValue</li>
</ul>
</td>
<td valign="top">
<table border="0">
<tbody>
<tr>
<td>
<ul>
<li>TDBXReader</li>
<li>TDataSet</li>
<li>TParams</li>
<li>TStream</li>
</ul>
</td>
</tr>
<tr>
<td>
<table border="0">
<tbody>
<tr>
<th>Collection DBXValue</th>
</tr>
<tr>
<td>
<ul>
<li>TDBXReaderValue</li>
<li>TDBXStreamValue</li>
</ul>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
<td valign="top">
<table border="0">
<tbody>
<tr>
<td>
<ul>
<li>TDBXConnection</li>
</ul>
</td>
</tr>
<tr>
<td>
<table border="0">
<tbody>
<tr>
<th>Connection DBXValue</th>
</tr>
<tr>
<td>
<ul>
<li>TDBXConnectionValue</li>
</ul>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<p>The following table summarizes differences between "Basic" and "Basic DBXValue" types:</p>
<table border="1" cellpadding="4">
<tbody>
<tr>
<td rowspan="2"> </td>
<th rowspan="2">Supports null values</th>
<th colspan="3">Declaration</th>
<th colspan="2">Accessing Values</th>
<th rowspan="2">Proxy generator</th>
</tr>
<tr>
<th>Default parameter direction</th>
<th>Other parameter directions</th>
<th>function result type</th>
<th>Get</th>
<th>Set</th>
</tr>
<tr>
<th>Basic</th>
<td align="center">No</td>
<td>
<p align="center"><span>in</span></p>
</td>
<td>
<p align="center">in/out: use <em>var</em> keyword<br />
out: use <em>out</em> keyword</td>
<td>
<p align="center"><span>Yes</span></p>
</td>
<td>lhs := AParameter</td>
<td>AParameter := rhs</td>
<td>
<p align="center"><span>Yes </span></p>
</td>
</tr>
<tr>
<th>DBXValue</th>
<td>
<p align="center">Yes</p>
</td>
<td>
<p align="center">in/out</p>
</td>
<td>
<p align="center">None</p>
</td>
<td>
<p align="center">No</p>
</td>
<td>AParameter.IsNull<br />
lhs:=AParameter.GetInt32,<br />
lhs:=AParameter.GetString, etc.</td>
<td>AParameter.SetNull<br />
AParameter.SetInt32(rhs),<br />
AParameter.SetString(rhs), etc.</td>
<td>
<p align="center">No</p>
</td>
</tr>
</tbody>
</table>
<p><br />
<h4>Supports null values</h4>
<p>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.</p>
<h4>Declaration</h4>
<p>The <em>var</em> and <em>out</em> 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.</p>
<h4>Proxy Generator</h4>
<p>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:</p>
<pre>// 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;</pre>
<p>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.  </p>
<h4>Accessing Values</h4>
<p>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.  </p>
<table border="1" cellpadding="4">
<tbody>
<tr>
<th>Get method</th>
<th>Set method</th>
<th>Type</th>
<th>Use with</th>
</tr>
<tr>
<td>GetAnsiString</td>
<td>SetAnsiString</td>
<td>AnsiString</td>
<td>TDBXAnsiCharsValue, TDBXAnsiStringValue</td>
</tr>
<tr>
<td>GetBcd</td>
<td>SetBcd</td>
<td>TBcd</td>
<td>TDBXBcdValue</td>
</tr>
<tr>
<td>GetBoolean</td>
<td>SetBoolean</td>
<td>Boolean</td>
<td>TDBXBooleanValue</td>
</tr>
<tr>
<td>GetDate</td>
<td>SetDate</td>
<td>TDBXDate</td>
<td>TDBXDateValue</td>
</tr>
<tr>
<td>GetDouble</td>
<td>SetDouble</td>
<td>Double</td>
<td>TDBXDoubleValue</td>
</tr>
<tr>
<td>GetInt16</td>
<td>SetInt16</td>
<td>Int16</td>
<td>TDBXInt16Value</td>
</tr>
<tr>
<td>GetInt32</td>
<td>SetInt32</td>
<td>Int32</td>
<td>TDBXInt32Value</td>
</tr>
<tr>
<td>GetInt64</td>
<td>SetInt64</td>
<td>Int64</td>
<td>TDBXInt64Value</td>
</tr>
<tr>
<td>GetSingle</td>
<td>SetSingle</td>
<td>Single</td>
<td>TDBXSingleValue</td>
</tr>
<tr>
<td>SetString</td>
<td>GetString</td>
<td>string</td>
<td>TDBXStringValue, TDBXWideCharsValue, TDBXWideStringValue</td>
</tr>
<tr>
<td>GetTime</td>
<td>SetTime</td>
<td>TDBXTime</td>
<td>TDBXTimeValue</td>
</tr>
<tr>
<td>GetTimeStamp</td>
<td>SetTimeStamp</td>
<td>TSQLTimeStamp</td>
<td>TDBXTimeStampValue</td>
</tr>
<tr>
<td>GetWideString</td>
<td>SetWideString</td>
<td>UnicodeString (same as string)</td>
<td>TDBXStringValue, TDBXWideCharsValue, TDBXWideStringValue</td>
</tr>
</tbody>
</table>
<p><br />
<h4>String Value Types</h4>
<p>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.  </p>
<table border="1" cellpadding="4">
<tbody>
<tr>
<th>Declared Type</th>
<th>Actual Type</th>
</tr>
<tr>
<td>TDBXAnsiCharsValue</td>
<td>TDBXAnsiCharsValue</td>
</tr>
<tr>
<td>TDBXAnsiStringValue</td>
<td>TDBXAnsiCharsValue</td>
</tr>
<tr>
<td>TDBXStringValue</td>
<td>TDBXWideCharsValue</td>
</tr>
<tr>
<td>TDBXWideCharsValue</td>
<td>TDBXWideCharsValue</td>
</tr>
<tr>
<td>TDBXWideStringValue</td>
<td>TDBXWideCharsValue</td>
</tr>
</tbody>
</table>
<p></p>
<h4>Sample Client And Server Applications</h4>
<p>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:</p>
<pre>{$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}</pre>
<p>Then I’ve used TTestBasicDBXValueType to declare and implement server methods classes for a variety of DBXValue types, such as TDBXInt32Value, TTestDBXDateValue , etc.</p>
<pre>  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;</pre>
<p>Consult the sample server to see how I&#8217;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.</p>
<p>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:<br />
<a href="/files/2009/03/dsclientserver2_1102.jpg"><img src="/files/2009/03/dsclientserver2_1102.jpg" alt="" width="686" height="511" /></a><br />
The following table shows the parameter types and return types demonstrated in the sample client and server:</p>
<table border="1" cellpadding="4">
<tbody>
<tr>
<th>Type</th>
<th>(in/out)</th>
<th>var</th>
<th>out</th>
<th>Result</th>
</tr>
<tr>
<td>TDBXAnsiCharsValue</td>
<td>X</td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td>TDBXAnsiStringValue</td>
<td>X</td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td>TDBXBcdValue</td>
<td>X</td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td>TDBXBooleanValue</td>
<td> X</td>
<td>  </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td>TDBXDateValue</td>
<td>X</td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td>TDBXDoubleValue</td>
<td>X</td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td>TDBXInt16Value</td>
<td>X</td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td>TDBXInt32Value</td>
<td>X</td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td>TDBXInt64Value</td>
<td>X</td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td>TDBXSingleValue</td>
<td>X</td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td>TDBXStringValue</td>
<td>X</td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td>TDBXTimeValue</td>
<td>X</td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td>TDBXTimeStampValue</td>
<td>X</td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td>TDBXWideCharsValue</td>
<td>X</td>
<td> </td>
<td> </td>
<td> </td>
</tr>
<tr>
<td>TDBXWideStringValue</td>
<td>X</td>
<td> </td>
<td> </td>
<td> </td>
</tr>
</tbody>
</table>
<p>That’s all for now.  I plan on covering the collection types in my next post.</p>
<p class="akst_link"><a href="http://blogs.embarcadero.com/jimtierney/?p=31407&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_31407" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=DataSnap%20Server%20Method%20DBXValue%20Parameters&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fjimtierney%2F2009%2F03%2F12%2F31407" id="akst_email_31407" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/jimtierney/2009/03/12/31407/feed</wfw:commentRss>
		</item>
		<item>
		<title>DataSnap Server Methods Parameters</title>
		<link>http://blogs.embarcadero.com/jimtierney/2009/02/13/31362</link>
		<comments>http://blogs.embarcadero.com/jimtierney/2009/02/13/31362#comments</comments>
		<pubDate>Fri, 13 Feb 2009 11:21:15 +0000</pubDate>
		<dc:creator>Jim Tierney</dc:creator>
		
		<category><![CDATA[DataSnap]]></category>

		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[Generics]]></category>

		<category><![CDATA[Server Methods]]></category>

		<guid isPermaLink="false">http://blogs.codegear.com/jimtierney/?p=31362</guid>
		<description><![CDATA[Delphi 2009 introduced support for DataSnap server methods. If you are not familiar with this feature, here are two articles that describe server methods: DataSnap 2009 Overview , Getting Started with Delphi DataSnap 2009.
DataSnap server methods support a variety of parameter and return types. The following list shows the types grouped into my own categories. 
This post [...]]]></description>
			<content:encoded><![CDATA[<p>Delphi 2009 introduced support for DataSnap server methods. If you are not familiar with this feature, here are two articles that describe server methods: <a href="http://dn.codegear.com/article/38682">DataSnap 2009 Overview </a>, <a href="http://blogs.codegear.com/pawelglowacki/2009/01/20/38649">Getting Started with Delphi DataSnap 2009</a>.</p>
<p>DataSnap server methods support a variety of parameter and return types. The following list shows the types grouped into my own categories. </p>
<p>This post is about "Basic" types.  The sample client and server projects that go with this post can be downloaded here: <a href="http://cc.codegear.com/item/26702">http://cc.codegear.com/item/26702</a></p>
<table border="0">
<tbody>
<tr>
<th>Basic</th>
<th>DBXValue</th>
<th>Collection</th>
<th>Connection</th>
</tr>
<tr>
<td valign="top">
<ul>
<li>AnsiString</li>
<li>Boolean</li>
<li>Currency</li>
<li>TDateTime</li>
<li>TDBXDate</li>
<li>TDBXTime</li>
<li>Double</li>
<li>Int64</li>
<li>Integer</li>
<li>LongInt</li>
<li>OleVariant</li>
<li>Single</li>
<li>SmallInt</li>
<li>WideString</li>
</ul>
</td>
<td valign="top">
<ul>
<li>TDBXAnsiStringValue</li>
<li>TDBXAnsiCharsValue</li>
<li>TDBXBcdValue</li>
<li>TDBXBooleanValue</li>
<li>TDBXConnectionValue</li>
<li>TDBXDateValue</li>
<li>TDBXDoubleValue</li>
<li>TDBXInt16Value</li>
<li>TDBXInt32Value</li>
<li>TDBXInt64Value</li>
<li>TDBXReaderValue</li>
<li>TDBXSingleValue</li>
<li>TDBXStreamValue</li>
<li>TDBXStringValue</li>
<li>TDBXTimeStampValue</li>
<li>TDBXTimeValue</li>
<li>TDBXWideCharsValue</li>
<li>TDBXWideStringValue</li>
</ul>
</td>
<td valign="top">
<ul>
<li>TDBXReader</li>
<li>TDataSet</li>
<li>TParams</li>
<li>TStream</li>
</ul>
</td>
<td valign="top">
<ul>
<li>TDBXConnection</li>
</ul>
</td>
</tr>
</tbody>
</table>
<p><a href="http://blogs.codegear.com/pawelglowacki/2009/01/20/38649">Getting Started with Delphi DataSnap 2009</a> uses the following function as an <span>exa</span>mple of a server method:</p>
<pre>function TDSServerModule1.Echo(s: string): string;
begin
 Result := 'Delphi DataSnap 2009 is echoing ' + s + ' ....' + s;
end;</pre>
<p>The proxy generator generates the following code to call this method:</p>
<pre>function TDSServerModule1Client.Echo(s: string): string;
begin
  if FEchoCommand = nil then
   begin
     FEchoCommand := FDBXConnection.CreateCommand;
     FEchoCommand.CommandType := TDBXCommandTypes.DSServerMethod;
     FEchoCommand.Text := 'TDSServerModule1.Echo';
     FEchoCommand.Prepare;
   end;
   FEchoCommand.Parameters[0].Value.SetWideString(s);
   FEchoCommand.ExecuteUpdate;
   Result := FEchoCommand.Parameters[1].Value.GetWideString;
end;</pre>
<p>I wanted my sample server and client to work like the sample in the article, with simple server methods and  generated proxy in the client.  In addition, I wanted to support various types so started with this generic server method implementation:</p>
<pre>{$METHODINFO ON}
 TTestBasicType = class(TComponent)
     function Echo(I: T): T;
 end;
{$METHODINFO OFF}

 function TTestBasicType.Echo(I: T): T;
 begin
   Result := I;
 end;</pre>
<p>The I used TTestBasicType used to declare and implement "Echo" methods for a variety of types, such as string, boolean, and double:</p>
<pre>TTestString = class(TTestBasicType&lt;string&gt;))
end;

TTestBoolean = class(TTestBasicType&lt;Boolean&gt;)
end; 

TTestDouble = class(TTestBasicType&lt;Double&gt;))
end;</pre>
<p>To test parameters directions, I expanded the generic class with var and out parmeters:</p>
<pre>{$METHODINFO ON}
TTestBasicType = class(TComponent)
  function Echo(I: T): T;
  procedure Copy(I: T; out J: T);
  procedure Swap(var I: T; var J: T);
end;
{$METHODINFO OFF}</pre>
<p>Consult the sample server to see how I&#8217;ve implemented the "plumbing" to make these classes callable by a DataSnap client. The implementation is unconventional because the TDSServerClass component is not used.</p>
<p>The sample VCL client is built starting with a TSQLConnection component. After setting the port and host name, I right clicked on the TSQLConnection and selected "Generate DataSnap client classes" to generate a client proxy:</p>
<p>In the generated code, there is a "Client" class for every one of the server classes. For <span style="color: #ffffff">exa</span>mple, TTestBooleanClient calls the TTestBoolean class on the server:</p>
<pre>TTestBooleanClient = class
private
  FDBXConnection: TDBXConnection;
  FInstanceOwner: Boolean;
  FEchoCommand: TDBXCommand;
  FCopyCommand: TDBXCommand;
  FSwapCommand: TDBXCommand;
public
  constructor Create(ADBXConnection: TDBXConnection);overload;
  constructor Create(ADBXConnection: TDBXConnection; AInstanceOwner: Boolean); overload;
  destructor Destroy; override;
  function Echo(I: Boolean): Boolean;
  procedure Copy(I: Boolean; out J: Boolean);
  procedure Swap(var I: Boolean; var J: Boolean);
end;</pre>
<p>Here is the implementation of TTestBooleanClient.Echo.  Consult the sample code to see the complete proxy implementation.  </p>
<pre>function TTestBooleanClient.Echo(I: Boolean): Boolean;
begin
 if FEchoCommand = nil then
 begin FEchoCommand := FDBXConnection.CreateCommand;
   FEchoCommand.CommandType := TDBXCommandTypes.DSServerMethod;
   FEchoCommand.Text := 'TTestBoolean.Echo';
   FEchoCommand.Prepare;
 end; FEchoCommand.Parameters[0].Value.SetBoolean(I);
 FEchoCommand.ExecuteUpdate;
 Result := FEchoCommand.Parameters[1].Value.GetBoolean;
end;</pre>
<p>The sample client tests the generated methods by calling them with sample values and verifying the results. Consult the sample for implementation details.</p>
<p>Here is screen shot of the running server and client:</p>
<p> <a href="/files/2009/02/dsclientserver_993.jpg"><img src="/files/2009/02/dsclientserver_993.jpg" alt="" width="541" height="355" /></a><a href="/files/2009/02/dsclientserver_990.jpg"></a></p>
<p>The following table shows the parameter types and return types demonstrated in the sample client and server:</p>
<table border="1">
<tbody>
<tr>
<th>Type</th>
<th>(in)</th>
<th>var</th>
<th>out</th>
<th>Result</th>
</tr>
<tr>
<td>AnsiString</td>
<td>X</td>
<td> </td>
<td> </td>
<td>X</td>
</tr>
<tr>
<td>Boolean</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<td>Currency</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<td>TDateTime</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<td>DBXDate</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<td>DBXTime</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<td>Double</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<td>Int64</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<td>Integer</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<td>LongInt</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<td>OleVariant</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td> </td>
</tr>
<tr>
<td>Single</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<td>SmallInt</td>
<td>X</td>
<td>X</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<td>String</td>
<td>X</td>
<td> </td>
<td> </td>
<td>X</td>
</tr>
<tr>
<td>WideString</td>
<td>X</td>
<td> </td>
<td> </td>
<td>X</td>
</tr>
</tbody>
</table>
<p>There are some Delphi types that you might expect to see in this list such as Byte and Cardinal. DataSnap currently doesn&#8217;t support these two nor LongWord, ShortInt, Word, TSQLTimeStamp, and TBcd. Support for var and out strings is coming (a workaround/alternative is to use TDBXStringValue in place of var String and TDBXAnsiStringValue in place of var AnsiString).</p>
<p>Thats all for now. I plan to cover more types in the future.</p>
<p class="akst_link"><a href="http://blogs.embarcadero.com/jimtierney/?p=31362&amp;akst_action=share-this"  title="Post to del.icio.us, etc." id="akst_link_31362" class="akst_share_link" rel="nofollow">Share This</a> | <a href="mailto:?subject=DataSnap%20Server%20Methods%20Parameters&body=Have you seen this? http%3A%2F%2Fblogs.embarcadero.com%2Fjimtierney%2F2009%2F02%2F13%2F31362" id="akst_email_31362" class="akst_share_email" rel="nofollow">Email this page to a friend</a></p>]]></content:encoded>
			<wfw:commentRss>http://blogs.embarcadero.com/jimtierney/2009/02/13/31362/feed</wfw:commentRss>
		</item>
	</channel>
</rss>

