Update Forms data
Updating Forms data is just about as easy as creating new records:
- Read the schema and the set of data which you want to update;
- Update records in your DataSet with appropriate field values;
- Call the Forms UpdateRecords() method to update the specified records.
There are a few subtleties, though. First of all: you don't always need to query for the records you'll be updating; if you already know their RecordURIs, that's enough. So you might use something like this instead:
- Know a list of RecordURIs which should be updated;
- Read the schema of the form, constructing a DataSet with this schema but no records;
- Create new records in your DataSet, each having a RecordURI and the new field values for that record;
- Call the Forms UpdateRecords() method.
Secondly, if you don't want to update every field in a record, you really don't need to include the unchanged fields in the dataset parameter to UpdateRecords(). The update data set only needs to include, at a minimum, the RecordURI field and the fields which are being changed. (This can lead to some performance benefits, if you're only updating one or two fields on a wide record).
For example, if you want to set Status field to "Overdue" for all records whose "DueDate" value is in the past, you could implement like this: removing the unnecessary columns will improve the performance of the web services call.
- Query (for schema and data) where String.Format("DueDate < #{0}#", nowstring);
- Update records in the DataSet with new values for the Status field;
- Remove un-needed columns from the table's schema;
- Call the Forms UpdateRecords() method.
NOTE: None of these examples are transactionally safe. You're making two separate web services calls: one to retrieve a set of data (or their RecordURIs), and another to update those records. In between those two calls, the data might have changed: field values might be different already, or the records might have been deleted, or other records might have been created in the tool which you don't know about yet. Groove Web Services doesn't include any mechanisms to create a "lock" on the data across multiple calls, so you need to use some appropriate defensive strategy. I should blog about some approaches for dealing with this type of update "safely", but that will have to wait for another day.
Anyhow; here's some code. First, my Update method in my helper class:
public void Update(System.Data.DataSet dataSet)
{
if (!IsDesignInitialized)
{
throw new Exception("Forms tool design is not initialized.");
}
GrooveForms2WebService.Forms2RecordDataSet formsDs = new GrooveForms2WebService.Forms2RecordDataSet();
dataSet.AcceptChanges();
string str = dataSet.GetXmlSchema();
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(str);
XmlElement[] schemaArray = new XmlElement[1];
schemaArray[0] = xmlDoc.DocumentElement;
formsDs.Schema = schemaArray;
str = dataSet.GetXml();
xmlDoc.LoadXml(str);
XmlNodeList nodelist = xmlDoc.DocumentElement.ChildNodes;
XmlElement[] dataArray = new XmlElement[nodelist.Count];
int j = 0;
foreach (XmlNode node in nodelist)
{
dataArray[j] = (XmlElement)node;
j++;
}
formsDs.Data = dataArray;
GrooveForms2WebService.GrooveForms2 svc = GetDataService();
svc.UpdateRecords(formsDs, true);
}
Then a short example following the third approach above, to set a Status field.
GrvFormsTool tool = new GrvFormsTool( . . . . );
// Query for overdue records
string nowstring = DateTime.Now.ToUniversalTime().ToString("yyyy'-'MM'-'ddTHH':'mm':'ss'.'fff'Z'");
string query = String.Format("DueDate < #{0}#", nowstring);
DataSet ds = tool.Query(query);
if (ds.Tables.Count > 0)
{
// Assume we already know which form (==table)
DataTable dt = ds.Tables[0];
// Set the status field on each row
foreach (DataRow dr in dt.Rows)
{
dr["Status"] = "Overdue";
}
// Remove columns other than Status and RecordURI
List<string> columnsToDelete = new List<string>();
foreach (DataColumn dc in dt.Columns)
{
string cn = dc.ColumnName;
if (cn != "RecordURI" && cn != "Status")
{
columnsToDelete.Add(cn);
}
}
foreach (string c in columnsToDelete)
{
dt.Columns.Remove(c);
}
dt.AcceptChanges();
tool.Update(ds);
}
(OK, I'm sure there are more concise ways to deal with a DataSet than this. My ignorance is all over.)
That caveat, again: this is not transactionally safe, so all sorts of things might happen 'twixt query and update.