Language

Visual Basic

C#

Show All

fcSDK Documentation Send comments on this topic.

Accessing Data with the Web Services

In this Section


Note: The Web Services have been moved to to a public GitHub repository: dovetail-sdk-web-services. Please use the services there to view the code, fork it, etc. The documentation provided here is still applicable, but Web Services are not included as part of the fcSDK installation.

Overview


The ClarifyDataAccessWS class, which is part of the fcSDK Web Services Client, provides an abstraction of the powerful ClarifyGeneric which can be use with web services. ClarifyDataAccessWS allows you to query data as well as make modifications. In each case, messages are built on the client side of the web services which describe what ClarifyGeneric instructions to be processed on the server side of the web services. Please see "Accessing Data with ClarifyGeneric" for details on generics and how to use them.

Querying Data


You query data by creating an instance of the DataQuery class and providing it with the information it needs to preform the desired query. You can specify the fields which get returned as well as filter and sorting criteria.

The following example will query for sites whose type is 1, sorted by ID Number descending. The example will then print out each site queried.

[C#] 

// Create an instance of data access client using a valid client session
ClarifyDataAccessWS clarifyDA = new ClarifyDataAccessWS( session );

//   Get all sites whose 'type' is 1 and sort by site ID, descending
DataQuery siteQuery = clarifyDA.CreateDataQuery("site");
siteQuery.DataFields.AddRange(new string[]{"objid", "site_id", "name"});
siteQuery.AppendFilter( "type", "Equals", "1" );
siteQuery.AppendSort( "site_id", false );

// Now query the data and return the result
string result = siteQuery.Query();

// Output the result to the console
Console.WriteLine(result);

All results from queries are returned as an XML string. The previous example would output something similar to the following:

<ClarifyGenericQuery>
	<site objid="268435458" site_id="NA" name="Unknown" />
	<site objid="268436436" site_id="999" name="Test Site 1" />
	<site objid="268436435" site_id="998" name="Test Site 2" />
	<site objid="268436434" site_id="997" name="Test Site 3" />
	<site objid="268436433" site_id="996" name="Test Site 4" />
	<site objid="268436432" site_id="995" name="Test Site 5" />
	<site objid="268436431" site_id="994" name="Test Site 6" />
	<site objid="268436430" site_id="993" name="Test Site 7" />
	<site objid="268436429" site_id="992" name="Test Site 8" />
</ClarifyGenericQuery>

You may then read the XML data as you wish (i.e. XmlDocument). You may also specify that the query return schema information for the fields selected so that you can load the results into a ADO.NET DataSet.

[C#] 

// Create an instance of data access client using a valid client session
ClarifyDataAccessWS clarifyDA = new ClarifyDataAccessWS( session );

//   Get all sites whose 'type' is 1 and sort by site ID, descending
DataQuery siteQuery = clarifyDA.CreateDataQuery("site");
siteQuery.DataFields.AddRange(new string[]{"objid", "site_id", "name"});
siteQuery.AppendFilter( "type", "Equals", "1" );
siteQuery.AppendSort( "site_id", false );

// Now query the data and return the result with schema information
string result = siteQuery.Query(true);

// Create a string reader to read the result
System.IO.StringReader reader = new System.IO.StringReader(result);

// Create and load the DataSet with the result
DataSet ds = new DataSet();
ds.ReadXml( reader );

// Get the site table from the DataSet
DataTable siteTable = ds.Tables["site"];

The DataQuery class also allows you to traverse relations just as you can with the ClarifyGeneric. Calling the Traverse method allows you to specify the relation to traverse and returns a new instance of the DataQuery class that for the table or view that is the result of that relation.

[C#] 

// Create an instance of data access client using a valid client session
ClarifyDataAccessWS clarifyDA = new ClarifyDataAccessWS( session );

//   Get all sites whose 'type' is 1 and sort by site ID, descending
DataQuery siteQuery = clarifyDA.CreateDataQuery("site");
siteQuery.DataFields.AddRange(new string[]{"objid", "site_id", "name"});
siteQuery.AppendFilter( "type", "Equals", "1" );
siteQuery.AppendSort( "site_id", false );

//   Get the primary address for the site by doing a traverse
DataQuery addressQuery = siteQuery.Traverse( "cust_primaddr2address" );

// Specify Data Fields to return
addressQuery.DataFields.AddRange( new string[]{"address", "city", "state", "zipcode"} );

// Now query the data and return the result
string result = siteQuery.Query();

// Output the result to the console
Console.WriteLine(result);

Data is return in a hierarchical structure and each relation is nested within it's parent object in the traversal. The previous example would output something similar to the following:

<ClarifyGenericQuery>
	<site objid="268435458" site_id="NA" name="Unknown">
		<address address="Not Available" city="Not Available" state="CA" zipcode="00000" />
	</site>
	<site objid="268436436" site_id="999" name="Test Site 1">
		<address address="123 street" city="Austin" state="TX" zipcode="78759" />
	</site>
	<site objid="268436435" site_id="998" name="Test Site 2">
		<address address="123 street" city="Austin" state="TX" zipcode="78759" />
	</site>
	<site objid="268436434" site_id="997" name="Test Site 3">
		<address address="123 street" city="Austin" state="TX" zipcode="78759" />
	</site>
	<site objid="268436433" site_id="996" name="Test Site 4">
		<address address="123 street" city="Austin" state="TX" zipcode="78759" />
	</site>
	<site objid="268436432" site_id="995" name="Test Site 5">
		<address address="123 street" city="Austin" state="TX" zipcode="78759" />
	</site>
</ClarifyGenericQuery>

If the following result is loaded into a DataSet, a row will be created for each address within a site even if the address record is the same for all the sites, therefore creating duplicate address rows.

The order it which objects are traversed affects how the data will be nested. For example, by traversing from the 'address' table to the 'site' table, the site information will be nested within the address tag.

[C#] 

// Create an instance of data access client using a valid client session
ClarifyDataAccessWS clarifyDA = new ClarifyDataAccessWS( session );

//   Get the address
DataQuery addressQuery = clarifyDA.CreateDataQuery("address");

// Specify Data Fields to return and filters
addressQuery.DataFields.AddRange( new string[]{"objid", "address", "city", "state", "zipcode"} );
addressQuery.AppendFilter( "objid", "Equals", "268435473" );

//  Traverse from address and get all sites whose 'type' is 1 and sort by site ID, descending
DataQuery siteQuery = addressQuery.Traverse("primary_addr2site");
siteQuery.DataFields.AddRange(new string[]{"objid", "site_id", "name"});
siteQuery.AppendFilter( "type", "Equals", "1" );
siteQuery.AppendSort( "site_id", false );

// Now query the data and return the result
string result = addressQuery.Query();

// Output the result to the console
Console.WriteLine(result);

<ClarifyGenericQuery>
	<address objid="268435473" address="123 street" city="Austin" state="TX" zipcode="78759">
		<site objid="268435458" site_id="NA" name="Unknown" />
		<site objid="268436436" site_id="999" name="Test Site 1" />
		<site objid="268436435" site_id="998" name="Test Site 2" />
		<site objid="268436434" site_id="997" name="Test Site 3" />
		<site objid="268436433" site_id="996" name="Test Site 4" />
		<site objid="268436432" site_id="995" name="Test Site 5" />
	</address>
</ClarifyGenericQuery>

You many have the need to use a table more than once within your DataQuery hierarchy which will require you to specify a user defined name for the output table. The following example shows how to query for three different addresses for a site.

[C#] 

// Create an instance of data access client using a valid client session
ClarifyDataAccessWS clarifyDA = new ClarifyDataAccessWS( session );

//   Get all sites whose 'type' is 1 and sort by site ID, descending
DataQuery siteQuery = clarifyDA.CreateDataQuery("site");
siteQuery.DataFields.AddRange(new string[]{"objid", "site_id", "name"});
siteQuery.AppendFilter( "type", "Equals", "1" );
siteQuery.AppendSort( "site_id", false );

//   Get the addresses and specify names for result tables
DataQuery primaryAddress = siteQuery.Traverse( "cust_primaddr2address", "primaryAddress" );
DataQuery shipAddress = siteQuery.Traverse( "cust_shipaddr2address", "shipAddress" );
DataQuery billAddress = siteQuery.Traverse( "cust_billaddr2address", "billAddress" );

// Specify Data Fields to return
primaryAddress.DataFields.AddRange( new string[]{"address", "city", "state", "zipcode"} );
shipAddress.DataFields.AddRange( new string[]{"address", "city", "state", "zipcode"} );
billAddress.DataFields.AddRange( new string[]{"address", "city", "state", "zipcode"} );

// Now query the data and return the result
string result = siteQuery.Query();

// Output the result to the console
Console.WriteLine(result);

<ClarifyGenericQuery>
	<site objid="268435458" site_id="NA" name="Unknown">
		<primaryAddress address="Not Available" city="Not Available" state="CA" zipcode="00000" />
		<shipAddress address="Not Available" city="Not Available" state="CA" zipcode="00000" />
		<billAddress address="Not Available" city="Not Available" state="CA" zipcode="00000" />
	</site>
	<site objid="268436436" site_id="999" name="Test Site 1">
		<primaryAddress address="123 street" city="Austin" state="TX" zipcode="78759" />
		<shipAddress address="123 street" city="Austin" state="TX" zipcode="78759" />
		<billAddress address="123 street" city="Austin" state="TX" zipcode="78759" />
	</site>
	<site objid="268436435" site_id="998" name="Test Site 2">
		<primaryAddress address="123 street" city="Austin" state="TX" zipcode="78759" />
		<shipAddress address="123 street" city="Austin" state="TX" zipcode="78759" />
		<billAddress address="123 street" city="Austin" state="TX" zipcode="78759" />
	</site>
</ClarifyGenericQuery>

Modifying Data


Making modifications using the web services are done using the DataModifier class. You create an instance of the DataModifier class by calling the CreateDataModifier method of the ClarifyDataAccessWS class.

After you have an instance of the DataModifier class you can begin to specify your updates. The DataModifier class has four factory methods for creating objects (called Modifiers) which will represent actions taken on single records within the database. For example, if you wish to insert a new record, you will create a DeleteModifier which you will use to specify which record to delete.

[C#] 

// Get next id number for site
string siteIDNum = session.GetNextNumScheme("Site ID");

// Create an instance of data access client using a valid client session
ClarifyDataAccessWS clarifyDA = new ClarifyDataAccessWS( this.session );

// Create an instance of the data modifier client
DataModifier modifier = clarifyDA.CreateDataModifier();

// Create InsertModifier to insert a new record
InsertModifier siteInsert = modifier.CreateInsertModifier("mysite", "site");

// Specify values for fields
siteInsert.SetField( "site_id", siteIDNum );
siteInsert.SetField( "name", "My test site" );
siteInsert.SetField( "type", "1" );

// Execute the database modifications and get the results
ModifierResultProtocol[] insertResults = modifier.Update();

// Loop through each result and write information to the console
foreach(ModifierResultProtocol result in insertResults)
{
   Console.WriteLine(
      string.Format("Action:{0}, Table:{1}, Name:{2}, Objid:{3}",
         result.Action, result.Table, result.Name, result.Objid) );
}

The previous example would output something similar to the following:

Action:Insert, Table:site, Name:mysite, Objid:268438543

The DataModifier class allows you to relate two records just as you can with ClarifyGeneric. To relate one Modifier to another you call the RelateRecord method.

[C#] 

// Get next id number for site and case
string siteIDNum = session.GetNextNumScheme("Site ID");
string caseIDNum = session.GetNextNumScheme("Case ID");

// Create an instance of data access client using a valid client session
ClarifyDataAccessWS clarifyDA = new ClarifyDataAccessWS( this.session );

// Create an instance of the data modifier client
DataModifier modifier = clarifyDA.CreateDataModifier();

// Create InsertModifiers to insert a new records
InsertModifier siteInsert = modifier.CreateInsertModifier("mysite", "site");
InsertModifier caseInsert = modifier.CreateInsertModifier("mycase", "case");

// Set site fields
siteInsert.SetField( "site_id", siteIDNum );
siteInsert.SetField( "name", "My site test" );
siteInsert.SetField( "type", "1" );

// Relate site to case
siteInsert.RelateRecord("cust_loc2case", caseInsert );

// Set case fields
caseInsert.SetField( "title", "Test from docs" );
caseInsert.SetField( "id_number", caseIDNum );

// Execute the database modifications and get the results
ModifierResultProtocol[] insertResults = modifier.Update();

// Loop through each result and write information to the console
foreach(ModifierResultProtocol result in insertResults)
{
   Console.WriteLine(
      string.Format("Action:{0}, Table:{1}, Name:{2}, Objid:{3}",
      result.Action, result.Table, result.Name, result.Objid) );
}

The previous example would output something similar to the following:

Action:Insert, Table:site, Name:mysite, Objid:268438544
Action:Insert, Table:case, Name:mycase, Objid:268437676

When modifiying data you are only allow to represent on record with exactly one Modifier object. Therefore you can not update more than one record using a single Modifier. You may update serveral records by using a Modifier for each update. It it also possible to update a record base on it's relations to another record. You use the ReferenceModifier to reference a record with preforming an action on it. The following example show how to update the name of a site for a given case.

[C#] 

// Create an instance of the data modifier client
DataModifier modifier = clarifyDA.CreateDataModifier();

// Create modifier for updating site and reference a case
UpdateModifier siteUpdate = modifier.CreateUpdateModifier("mysite", "site");
ReferenceModifier caseUpdateRef = modifier.CreateReferenceModifier("mycase", "case");

// Set field to update on site
siteUpdate.SetField( "name", "new title from nunit" );

// Add a unique relation by case
siteUpdate.AppendUniqueRelation( "case_reporter2site", caseUpdateRef );

// Add a unique filter by case objid
caseUpdateRef.AppendUniqueFilter( "objid", caseObjid );

// Execute the database modifications and get the results
ModifierResultProtocol[] updateResults = modifier.Update();

// Loop through each result and write information to the console
foreach(ModifierResultProtocol result in updateResults)
{
   Console.WriteLine(
      string.Format("Action:{0}, Table:{1}, Name:{2}, Objid:{3}",
      result.Action, result.Table, result.Name, result.Objid) );
}

The previous example would output something similar to the following:

Action:Update, Table:site, Name:mysite, Objid:268438545
Action:Reference, Table:case, Name:mycase, Objid:268437677