Welcome to MSDN Blogs Sign in | Join | Help

Forms Data

When you read data from a Forms tool's web service, it's delivered in an XML format which is designed to map easily to a System.Data.DataSet.  Of course you could work with the raw XML, but dealing with a DataSet gives you lots of flexibility.

There are two parts to the dataset: its schema, and data.  With the Forms QueryRecords method you can query just for the schema information (metadata), or for data records as well.  Additionally there's a flag indicating whether you want the actual contents of file attachments (which we'll use later).  It's handy to have all these options in a single method.

public System.Data.DataSet GetDataSet(bool metadataOnly, bool includeAttachments, string queryString)

{

if (!IsDesignInitialized)

{

throw new Exception("Forms tool design is not initialized.");

}

GrooveForms2WebService.GrooveForms2 svc = GetDataService();

// Query for metadata, records (optional), and attachment contents (optional)

GrooveForms2WebService.RecordQuery recordQuery = new GrooveForms2WebService.RecordQuery();

recordQuery.FormURI = "";

recordQuery.ViewURI = "";

recordQuery.IncludeFileAttachmentContent = includeAttachments;

recordQuery.QueryMetadataOnly = metadataOnly;

recordQuery.UnreadRecordsOnly = false;

recordQuery.WhereClause = queryString;

// Ask service to query records

GrooveForms2WebService.Forms2RecordDataSet fds;

fds = svc.QueryRecords(recordQuery);

 

// Make a DataSet to contain the records

System.Data.DataSet recordDataSet = new System.Data.DataSet("RecordDataSet");

// If schema exists, load it into the DataSet

if (fds.Schema is System.Array)

{

System.Xml.XmlNode[] schemaNodes = (System.Xml.XmlNode[])fds.Schema;

foreach (System.Xml.XmlNode schemaNode in schemaNodes)

{

System.IO.StringReader schemaReader = new System.IO.StringReader("<?xml version=\"1.0\"?>" + schemaNode.OuterXml);

recordDataSet.ReadXmlSchema(schemaReader);

}

}

// If data exists, load it into the DataSet

if (fds.Data is System.Array)

{

System.Xml.XmlNode[] dataNodes = (System.Xml.XmlNode[])fds.Data;

foreach (System.Xml.XmlNode dataNode in dataNodes)

{

System.Xml.XmlNodeReader dataReader = new System.Xml.XmlNodeReader(dataNode);

recordDataSet.ReadXml( dataReader, System.Data.XmlReadMode.Auto );

}

}

recordDataSet.AcceptChanges();

recordDataSet.EnforceConstraints = false;

return recordDataSet;

}

I'm missing a couple of pieces from this: the FormURI and ViewURI in the record query.  Those are both really useful and important, but I'm being a bit lazy.  Rather than write the code, here's a little explanation of those two.

A Forms tool can contain one or more forms, and one or more views.  Each form defines the columns in a table in the tool's dataset.  So if we query the schema of a tool with two forms, there will be two tables in the DataSet we constructed with the code above (or sometimes more, if the form uses attachments).

Views define how to display a subset of records in the tool, from one or more forms, with columns displaying each field's contents.  A view's columns can be sorted, grouped, and so on, using the Forms Designer.  And a view's design can include a filter, selecting only records whose fields match some conditions you specify.  Typical uses would be to display only records with a particular value in a Status field, or only records which are assigned to the current user, and so on.

For good performance, it's very important to use Groove's own indexing and query capabilities as much as possible.  So if you want to find a subset of records from a certain form, with some value of a field, the worst possible approach is to query for all records (with the code above and an empty queryString value), then pick through them in your application's DataSet.  Instead, try to construct a query which returns exactly the records you need.

There are three ways to refine that query.

First: specify a FormURI, so the query results will only include records which use the specified form.  (Use the ReadForms() method to obtain the list of forms and their URIs).

Second: specify a ViewURI, so the query will only include records which appear in the specified view.  (Use the ReadViews() method to obtain a list of views and their URIs).  Besides performance, there's another great benefit to this option: your application logic, which decides how to select a subset of records, can be defined and maintained right in the forms tool itself (by building views appropriate to the types of query you need, for example to select records by status), rather than as hard-coded selection conditions baked into C# code.

Third: specify a query string.  This is equivalent to a (small but useful subset of) SQL "WHERE" clause... you can specify various field combinations and conditional operators, including the "LIKE" syntax.  (I won't go tthrough all the options here, since they're well documented, in the SDK's help file under GrooveForms2 Web Service.).

Finally, instead of the QueryRecords method used here, there's a ReadRecords() method which takes a list of record-URIs rather than a query.  If you know the URIs of the records you want, use ReadRecords().  But I'll skip over it for now.

Published Thursday, June 22, 2006 10:55 AM by hpyle

Comments

# EnforceConstraints

Wednesday, June 28, 2006 1:23 PM by hughpyle
It's really nice to see people try using the techniques I'm posting here.&amp;nbsp; But, as usual, there...
Anonymous comments are disabled
 
Page view tracker