The demos are built. The help file is writen. The installer is done.
Introducing kbmMW Spider 2 for dotnet 
Firstly a big thanks for the field testers. They made the product better and proven in a live environment including our own myc4d.com and turbomiddleware.com sites.
I thought I'd run through the shipping demos, they're kind of fun.
There is a W32 appilication server based on the standard BDE demo we ship with the framework. I decided to implement the classic biolife demo.
Here is a code sample form it's main service
function TTestQuery.ProcessRequest(const Func: string;
const ClientIdent: TkbmMWClientIdentity;
const Args: array of Variant): Variant;
begin
if (Func='FETCHBIOLIFE') then
StreamBiolife else
if (Func='FETCHBIOLIFEOBJECTS') then
StreamBiolifeObjects
else
inherited ProcessRequest(Func,ClientIdent,Args);
end;
procedure TTestQuery.StreamBiolife;
begin
self.BIOLIFE.Open;
try
self.BIOLIFE.SaveToStreamViaFormat(self.ResultStream,self.kbmMWBinaryStreamFormat1);
finally
self.BIOLIFE.Close;
end;
end;
There are two service methods supported. The first one simply opens BioLife.db and streams the resultset down the wire.
I have three demo clients. They are
- Winforms client built with VS2005
- VCL.net client built with D2007 for dotnet
- ASP.net client built with VS2005
Here is the important code for the Winforms sample
private void button1_Click(object sender, EventArgs e)
{
C4D.kbmMW.Transports.TCPIPTransport transport = new C4D.kbmMW.Transports.TCPIPTransport();
transport.Port = 3000;
transport.Host = "127.0.0.1";
transport.Connect();
C4D.kbmMW.Client.SimpleClient client = new C4D.kbmMW.Client.SimpleClient(transport);
C4D.kbmMW.Data.DataAdapter da = new C4D.kbmMW.Data.DataAdapter();
da.FormatterType = C4D.Common.Formatters.FormatterType.kbmMW;
client.SendRequest("KBMMW_QUERY", "", "FETCHBIOLIFE");
System.Data.DataTable dataTable = new DataTable("biolife");
da.FillDatatable(dataTable, client.ResultStream);
dataGrid.DataSource = dataTable;
dataGrid.Columns["Graphic"].AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells;
}
And here is the output
Cool
Here is the VCL.net code sample
procedure TForm1.Button1Click(Sender: TObject);
var
transport: C4D.kbmMW.Transports.TCPIPTransport;
client: C4D.kbmMW.Client.SimpleClient;
da: C4D.kbmMW.Data.DataAdapter;
dataTable: System.Data.DataTable;
ADOBridge: Borland.Vcl.ADONETDb.TADONETConnector;
begin
transport:= C4D.kbmMW.Transports.TCPIPTransport.Create;
transport.Port:= 3000;
transport.Host:= '127.0.0.1';
transport.Connect();
client:= C4D.kbmMW.Client.SimpleClient.Create(transport);
da:= C4D.kbmMW.Data.DataAdapter.Create;
da.FormatterType:= C4D.Common.Formatters.FormatterType.kbmMW;
client.SendRequest('KBMMW_QUERY', '', 'FETCHBIOLIFE');
dataTable:= System.Data.DataTable.Create('biolife');
da.FillDatatable(dataTable, client.ResultStream);
ADOBridge:= Borland.Vcl.ADONETDb.TADONETConnector.Create(nil);
ADOBridge.DataTable:= dataTable;
self.DataSource.DataSet:= ADOBridge;
self.DBGrid1.DataSource:= self.DataSource;
end;
and the output
The Delphi grid doesn't recognise the images - but owner draw would cope with that.
Here's the ASP.net VS2005 sample.
protected void Page_Load(object sender, EventArgs e)
{
// We're using a connection pool for this sample, see Global.cs
C4D.kbmMW.Client.PooledSimpleClient client = new C4D.kbmMW.Client.PooledSimpleClient(Global.ConnectionPool);
C4D.kbmMW.Data.DataAdapter da = new C4D.kbmMW.Data.DataAdapter();
da.FormatterType = C4D.Common.Formatters.FormatterType.kbmMW;
client.SendRequest("KBMMW_QUERY", "", "FETCHBIOLIFE");
System.Data.DataTable dataTable = new DataTable("biolife");
da.FillDatatable(dataTable, client.ResultStream);
this.GridView1.DataSource = dataTable;
this.GridView1.DataBind();
}
You will notice the use of Global.ConnectionPool
This is the connection pooling feature of Spider2 and is setup like this in Global.cs
public partial class Global : System.Web.HttpApplication
{
private static C4D.kbmMW.Client.ClientConnectionPool connectionPool;
public Global()
{
connectionPool = new C4D.kbmMW.Client.ClientConnectionPool();
C4D.kbmMW.Transports.TCPIPTransport transport = new C4D.kbmMW.Transports.TCPIPTransport();
transport.Host = "127.0.0.1";
transport.Port = 3000;
connectionPool.Template = transport;
}
public static C4D.kbmMW.Client.ClientConnectionPool ConnectionPool
{
get { return connectionPool; }
}
protected void Application_Start(Object sender, EventArgs e)
{
connectionPool.Active = true;
}
}
and the output
Finally, the DataAdapters use the VCL streaming support. There is nothing to stop us using this directly.
The second method on the server was
procedure TTestQuery.StreamBiolifeObjects;
var
writer: TWriter;
begin
writer:= TWriter.Create(self.ResultStream,1024);
self.BIOLIFE.Open;
try
writer.WriteInteger(self.BIOLIFE.RecordCount);
while not self.BIOLIFE.Eof do
begin
writer.WriteInteger(self.BIOLIFE.FieldByName('Species No').AsInteger);
writer.WriteString(self.BIOLIFE.FieldByName('Category').AsString);
writer.WriteString(self.BIOLIFE.FieldByName('Common_Name').AsString);
writer.WriteString(self.BIOLIFE.FieldByName('Species Name').AsString);
writer.WriteFloat(self.BIOLIFE.FieldByName('Length (cm)').AsFloat);
writer.WriteFloat(self.BIOLIFE.FieldByName('Length_In').AsFloat);
writer.WriteString(self.BIOLIFE.FieldByName('Notes').AsString);
self.BIOLIFE.Next;
end; // while
finally
writer.Free;
self.BIOLIFE.Close;
end;
end;
Here we use a TWriter component to write out the Biolife data directly onto the resultstream.
On the ASP.net client we have this code to decode it.
class BiolifeObject
{
private int speciesNo;
private string category;
private string commonName;
private string speciesName;
private double lengthCM;
private double lengthIn;
private string notes;
public int SpeciesNo
{
get { return this.speciesNo; }
set { this.speciesNo = value; }
}
public string Category
{
get { return category; }
set { category = value; }
}
public string CommonName
{
get { return commonName; }
set { commonName = value; }
}
public string SpeciesName
{
get { return speciesName; }
set { speciesName = value; }
}
public double LengthCM
{
get { return lengthCM; }
set { lengthCM = value; }
}
public double LengthIn
{
get { return lengthIn; }
set { lengthIn = value; }
}
public string Notes
{
get { return notes; }
set { notes = value; }
}
}
This is a class to accept the data and we bind it like this.
protected void Button1_Click(object sender, EventArgs e)
{
// We're using a connection pool for this sample, see Global.cs
C4D.kbmMW.Client.PooledSimpleClient client = new C4D.kbmMW.Client.PooledSimpleClient(Global.ConnectionPool);
client.SendRequest("KBMMW_QUERY", "", "FETCHBIOLIFEOBJECTS");
C4D.Common.VCL.VCLReader reader = new C4D.Common.VCL.VCLReader(client.ResultStream);
System.Collections.ArrayList objects = new System.Collections.ArrayList();
int ObjectCount = reader.ReadInteger();
while (ObjectCount > 0)
{
BiolifeObject bo = new BiolifeObject();
bo.SpeciesNo = reader.ReadInteger();
bo.Category = reader.ReadString();
bo.CommonName = reader.ReadString();
bo.SpeciesName = reader.ReadString();
bo.LengthCM = reader.ReadFloat();
bo.LengthIn = reader.ReadFloat();
bo.Notes = reader.ReadString();
objects.Add(bo);
ObjectCount--;
}
this.GridView1.DataSource = objects;
this.GridView1.DataBind();
}
We marshall the streamed data off the resultstream using a VCLReader and create an arraylist of Biolife objects. These can be bound to directly from the grid.
The output is as follows (hit FetchAsObjects), although the property ordering isn't maintained.
There you go and blindingly quick.
Look out for the release announcement. It will be available at MyC4D.com
Richard