Tamino API for .NET Version 8.2.2
 —  Tamino API for .NET  —

Processing Query Results

Each application processes data differently when it receives a response from Tamino as a result of a query. The Tamino API for .NET provides several methods and classes for accessing query results appropriately, satisfying various requirements for further processing.


Accessing Query Results as Stream and XmlReader

For further processing, it may be convenient to access the results of a query as a Stream; alternatively, it may be more convenient to access them as an XmlReader. These options are supported by the methods QueryStream and QueryReader of the TaminoCommand class, respectively.

The QueryXmlReader sample in the QuerySamples demonstrates using the QueryReader method to apply an XSL transformation to the query result.

Example

...
XmlReader reader = command.QueryReader(query);
XPathDocument xpathDoc = new XPathDocument(reader);

XslTransform xslTransform = new XslTransform();
xslTransform.Load("mystylesheet.xsl");

xslTransform.Transform(xpathDoc, null);
...

Top of page

Accessing Single Value Query Results

A query may return just one simple value as its result. The GetSingleItem method in the TaminoQueryResponse enables you to access a simple result simply. See also the IntegerQuery example in the QuerySamples.

Example

TaminoQuery query = new TaminoQuery("count(input()/Property")
TaminoQueryResponse qr = command.Query(query);
int result = (int) qr.GetSingleItem(typeof(int));

You can also specify a complex type as the parameter to the GetSingleItem method. Any type that can be serialized and deserialized by .NET's XmlSerializer class is supported.

Top of page

Iterating Through Query Results

The Tamino API for .NET provides two classes for iterating over query result sets: TaminoPageIterator and TaminoItemIterator. Your application can use the convenient foreach statement to iterate over the query results.

Both classes can be used to process query results, whether a Tamino cursor has been used for the query or not. Tamino cursor usage is completely hidden from the application. However, if a cursor was not used for the query, all the query result items are returned in one page and therefore there is only one page to iterate over.

The TaminoItemIterator can be used to iterate over the complete query result. Item iteration crosses page boundaries seamlessly.

Example

...
TaminoQueryResponse qr = command.Query(query, 10); // pagesize=10
foreach (XmlNode node in qr)
{
  	Console.WriteLine(node.OuterXml);
}
qr.Close();
...

The TaminoItemIterator can also be used in conjunction with a TaminoPageIterator, so that the application can navigate pagewise through the query result, and then request a TaminoItemIterator to iterate over the results within a single page.

Example

...
TaminoQueryResponse qr = command.Query(query, 10); // pagesize=10
TaminoPageIterator pageIt = qr.GetPageIterator();
foreach (XmlDocument page in pageIt)
{
   TaminoItemIterator itemIt = pageIt.GetItemIterator();
   foreach (XmlNode node in itemIt)
   {
      Console.WriteLine(node.OuterXml);
   }
}
qr.Close();
...

An application can iterate forwards and backwards over the query results.

Example

...
TaminoQueryResponse qr = command.Query(query, 10);  // pagesize=10
TaminoPageIterator pageIt = qr.GetPageIterator();
while(pageIt.Next())
{
   XmlDocument page = pageIt.GetPage();
   ...
}

while (pageIt.Previous())
{
   XmlDocument page = pageIt.GetPage();
   ...
}
qr.Close();
...

Note:
After modifying items in a page and writing the modifications back to the database, you will see the old values when you iterate over this page again.

See also the QueryPageIterator, QueryItemIterator and QueryNoTaminoCursor examples in the QuerySamples.

Top of page

Processing Document Lists

If the query result set is a list of complete root elements of Tamino XML documents, the application can use the serialization class TaminoXmlDocument to access the individual result items within this list, make modifications, and write the modified items back to the Tamino database.

Example

TaminoQuery query =
    TaminoXmlDocument.BuildQuery(null, "input()/Property[@Category=’Buy’]");

TaminoQueryResponse qr = command.Query(query, 10); // pagesize=10
TaminoItemIterator itemIt = qr.GetItemIterator();

while(itemIt.Next())
{
   TaminoXmlDocument doc =
       (TaminoXmlDocument) itemIt.GetItem(typeof(TaminoXmlDocument))

   XmlElement elem = (XmlElement) doc.Data;
   // ...make some changes to elem

   TaminoResponse response = command.Update(doc);
   ...
}

You can find the complete sample code in the ProcessingDocumentList sample of the QuerySamples.

Similarly, you can use the class TaminoXmlDocumentProperties to get a list of document properties which you can subsequently use to access the documents themselves. For more information, see the Tamino API for .NET Reference Documentation.

That’s all you need to know in order to use document lists successfully in your own applications. If you want to know more about this technique, the following paragraphs describes how it works internally.

Processing Document Lists: Internals

  1. TaminoXmlDocument.BuildQuery modifies the specified query expression so that the query result will look like this:

    <?xml version="1.0" encoding="iso-8859-1" ?>
    <ino:response ...>
       <xq:query>
       <![CDATA[ namespace
        tf='http://namespaces.softwareag.com/tamino/TaminoFunction' for $p in
        input()/Property[@Category='Buy'] return <TaminoDocument
        doctype={tf:getDoctype($p)}
        docid={tf:getInoId($p)}>{$p}</TaminoDocument>
        ]]>
       </xq:query>
       ...
       <xq:result xmlns:xq="http://namespaces.softwareag.com/tamino/XQuery/result"
                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                     xmlns:tf="http://namespaces.softwareag.com/tamino/TaminoFunction">
    	     <tan:TaminoDocument tan:docid="1" tan:doctype="Property"
                              xmlns:tan="http://namespaces.softwareag.com/tamino/TaminoAPI4DotNet">
             <Property Category="Buy" PropertyType="2-Room-Apartment">
                ...
             </Property>
          </tan:TaminoDocument>
          <tan:TaminoDocument tan:docid="2" tan:doctype="Property"
                              xmlns:tan="http://namespaces.softwareag.com/tamino/TaminoAPI4DotNet">
             <Property Category="Buy" PropertyType="4-Room-Apartment" >
                ...
             </Property>
          </tan:TaminoDocument>
       </xq:result>
    </ino:response>
    
  2. TaminoXmlDocument can be serialized and deserialized using .NET's XmlSerializer class. After deserializing the first result item by calling iterator.GetItem(typeof(TaminoXmlDocument)), the public fields and property of the TaminoXmlDocument object contain the following values:

    DocName "@1"
    DocType "Property"
    ContentType "text/xml"
    IsXml True
    Date
    <Property Category="Buy" PropertyType="2-Room-Apartment">
       ...
    </Property>
    
  3. TaminoXmlDocument implements the ITaminoDocument interface. This allows it to be passed on to the Update method of the TaminoCommand class.

Top of page

Processing Node Lists

An application can always update any node of a Tamino XML document by performing XQuery updates via the Query method of the TaminoCommand class in a descriptive way (see Performing Queries and Update Queries). However, if the query result set comprises a list containing uniform subtrees of a Tamino XML document, it may be better if the application uses a more object-oriented technique to access the individual result items, make modifications, and write the changes back to the Tamino database. The ProcessingNodeList example in the QuerySamples demonstrates using a simple class like MyXmlNode to process node lists more conveniently.

Example

...
string expr = "input()/Property/ContactPerson";

MyXmlNode.Selector = ".//ContactPerson";
MyXmlNode.Field = "Name";
TaminoQuery query = MyXmlNode.BuildQuery(expr);
TaminoQueryResponse queryResponse = command.Query(query, 10); // pagesize=10

TaminoItemIterator itemIt = queryResponse.GetItemIterator();

while (itemIt.Next())
{
   MyXmlNode item = (MyXmlNode) itemIt.GetItem(typeof(MyXmlNode));

   XmlNode contact = item.Data;
    // make some modifications
   TaminoQuery updateQuery = item.BuildUpdate();
   TaminoQueryResponse updateResponse = command.Query(updateQuery);
   ...
}
...

Processing Node Lists: Internals

To update an individual query result item, the item must be uniquely identified in the Tamino database. In this example, the MyXmlNode class uses a similar concept to the <unique> constraints as it is defined in XML Schema: the application specifies sub-tree uniqueness within the scope of the XML document that contains the sub-tree. This is done by setting MyXmlNode.Selector and MyXmlNode.Field accordingly. The MyXmlNode class uses the same mechanism as the TaminoXmlDocument class to identify the XML document.

The following steps are performed when modifying the phone number for a ContactPerson item:

  1. MyXmlNode.Selector = ".//ContactPerson" and MyXmlNode.Field="Name" specify how a single ContactPerson element can be uniquely identified within a Property document: each ContactPerson element is identified uniquely by its "Name" child. Notice that the scope of uniqueness is just a single document. The "Name" value does not have to be unique over all Property documents.

  2. MyXmlNode.BuildQuery(expr) modifies the specified query expression so that the query result will contain identifying information for the XML documents affected by this query.

    A single item in the query result set might look like this:

    <MyXmlNode doctype='Property' inoid='10'>
      <ContactPerson>
        <Name>Glenn Carter</Name>
        <Phone>1-361-842-3875</Phone>
        <Email>Glenn.Carter@automailer.com</Email>
      </ContactPerson>
    </MyXmlNode>
    
  3. When iterator.GetItem(typeof(MyXmlNode)) is executed for the item in step 2 above, the properties and fields of the MyXmlNode instance will contain the following values:

    TaminoInoId "10"
    DocType "Property"
    Data
    <ContactPerson>
      <Name>Glenn Carter</Name>
      <Phone>1-361-842-3875</Phone>
      <Email>Glenn.Carter@automailer.com</Email>
    </ContactPerson>
    
    m_oldfield "Glenn Carter"
  4. Assume that the application changes the Data property so that it contains the new phone number:

    <ContactPerson>
      <Name>Glenn Carter</Name>
      <Phone>9-999-999-9999</Phone>
      <Email> Glenn.Carter@automailer.com </Email>
    </ContactPerson>
    
  5. item.BuildUpdate() uses the MyXmlNode.Selector and MyXmlNode.Field settings and the m_oldfield and Data values to create the following update query:

    namespace tf='http://namespaces.softwareag.com/tamino/TaminoFunction' update replace for $p in input()/Property//ContactPerson where tf:getInoId($p)=10 and $p/Name="Glenn Carter" return $p with <ContactPerson><Name>Glenn Carter</Name><Phone>9-999-999-9999</Phone><Email>Glenn.Carter@automailer.com</Email></ContactPerson>

Top of page

Binding Query Results to Web Controls

TaminoQueryResponse, TaminoItemIterator and TaminoPageIterator implement .NET's IEnumerable and IEnumerator interfaces. This allows an application to bind query results directly to .NET Web controls.

The following example queries all names of contact persons from Tamino and shows them in a list box. You can find the Property schema and corresponding example data in the samples.

Example

...
protected System.Web.UI.WebControls.ListBox ListBox1;
...
TaminoQuery query = new TaminoQuery("input()/Property/ContactPerson/Name"));
TaminoQueryResponse qr = command.Query(query);
ListBox1.DataSource = qr;
ListBox1.DataTextField = "InnerText";
ListBox1.DataBind();
...

Top of page