XML String Building


How to build XML string with only changed rows/columns edit on user form?

Formerly I've been working on three-tier applications on J2EE platform. All aplication logic was written in EJB and all the data was send as XML string from PowerBuilder clients. I was thinking how to implement such kind of solution in .NET through ADO.NET. The most simple way is to send data as DataSet object which also includes XMLrepresetation of containing data objects (datatables, datacolumns, etc.). But sending the whole dataset has too much overhead. We only want to send changed/modified data to middle-tier .NET component. How to do this in aefficient manner?

The basic idea is to send only changed rows/columns of DataTable object. The method below takes two parameters:- DataTable table: only changed rows from input form/datagrid
- string keyColName: name of key column of table

We use three different statuses for row tag:
- "INSERT": new added row
- "UPDATE": updated row
- "DELETE": deleted row

/// <summary>
/// Returns XML string of changed DataTable rows
/// </summary>
public string GetXML(DataTable table, string keyColName) {
DataView ldvOriginal = new DataView(table);
DataView ldvChanged = new DataView(table);
DataView ldvAdded = new DataView(table);
DataView ldvDeleted = new DataView(table);
ldvOriginal.RowStateFilter = DataViewRowState.ModifiedOriginal;
ldvChanged.RowStateFilter = DataViewRowState.ModifiedCurrent;
ldvAdded.RowStateFilter = DataViewRowState.Added;
ldvDeleted.RowStateFilter = DataViewRowState.Deleted;

string lsXml = "<?xml version=\"1.0\"?>\n";
string lsStatusInsert = "<row status=\"INSERT\">\n";
string lsStatusUpdate = "<row status=\"UPDATE\">\n";
string lsStatusDelete = "<row status=\"DELETE\">\n";
int noAdded = ldvAdded.Count;
int noChanged = ldvChanged.Count;
int noDeleted = ldvDeleted.Count;

try {
// added rows
lsXml += "<" + table.TableName + ">\n";
for (int i=0; i < noAdded; i++) {
lsXml += lsStatusInsert;
foreach (DataColumn dc in ldvAdded.Table.Columns) {
if (ldvAdded[i][dc.ColumnName].ToString().Length > 0)
lsXml += "<" + dc.ColumnName + ">" +
ldvAdded[i][dc.ColumnName] +
"<" + dc.ColumnName + ">\n";
} // foreach column
lsXml += "</row>\n";
} // for
// modified rows
for (int i=0; i < noChanged; i++) {
lsXml += lsStatusUpdate;
foreach (DataColumn dc in ldvChanged.Table.Columns) {
if (keyColName.Equals(dc.ColumnName))
lsXml += "<" + dc.ColumnName + ">" +
ldvChanged[i][dc.ColumnName] +
"<" + dc.ColumnName + ">\n";
else
if (!ldvOriginal[i][dc.ColumnName].ToString().Equals(ldvChanged[i][dc.ColumnName].ToString()))
lsXml += "<" + dc.ColumnName + ">" +
ldvChanged[i][dc.ColumnName] +
"<" + dc.ColumnName + ">\n";
} // foreach column
lsXml += "</row>\n";
} // for
// deleted rows
for (int i=0; i < noDeleted; i++) {
lsXml += lsStatusDelete;
lsXml += "<" + keyColName + ">" + ldvDeleted[i][keyColName] + "<" + keyColName + ">\n";
lsXml += "</row>\n";
} // for
lsXml += "<" + table.TableName + ">\n";

} catch (Exception ex) {
throw ex;
}
return lsXml;
}

Example:

DataTable dt = new DataTable("DemoTable");
// we fill this table through DataAdapter Fill() method
// and we edit data in user control such as DataGrid, form,..
..

if (dt.GetChanges()!=null) {
string xml = this.GetXML(dt.GetChanges(), "customer_id");
// pass xml to middle-tier..

}

Method returns XML string which can be passed to middle tier. Here we parse it and do all necessary bussiness logic due to row status. We do not need XSD because we can get metadata in the middle tier component directly from database table.

Twitter Digg Delicious Stumbleupon Technorati Facebook Email

No comments yet... Be the first to leave a reply!