C#•Determine the Update Order of DataTables at Run Time

Listing 3. You can always find at least one correct sequence for performing a two-sweeps update procedure as long as the DataTables relationships form an acyclic graph—one with no closed-circuit paths. This is the C# implementation of such an algorithm. Note how the code takes advantage of DataSet's ExtendedProperties to mark a relationship as visited.

ArrayList ar = new ArrayList ();
DataSet ds = new DataSet ();
//set up a Dataset with tables and relationships
ds.ReadXmlSchema (@"dataset1.xsd");
Hashtable ht = new Hashtable ();

//make root table list (no incoming FK constraints)
foreach (DataTable dt in ds.Tables )
	ht.Add (dt.TableName, dt);
foreach(DataRelation dr in ds.Relations)
	if (ht.ContainsKey 
		ht.Remove (dr.ChildTable.TableName);

//set up DataTable update order. 
//Store it in ar ArrayList variable
foreach(DictionaryEntry de in ht) {
	DataTable dt = (DataTable)de.Value;
	//processTable contains core of algorithm
	processTable (dt,ar);

//First sweep: insert-update
foreach (DataTable l_tbl in ar) {
	//suppose the persistInsertAndUpdate method 
	//can find appropriate datadapter for 
	//the provided DataTable
//second sweep: delete
foreach (DataTable l_tbl in ar) 
	//suppose the commitDeletes method 
	//can find the appropriate datadapter for 
	//the provided DataTable

//the core routine
void processTable(DataTable p_dt, ArrayList p_ar) {
	p_ar.Add (p_dt);
	foreach(DataRelation l_childrel in 
		p_dt.ChildRelations) {
		bool l_ready=true;
		DataTable l_dtc = 
		//Check if there are other incoming 
		//relations not visited yet. If not, 
		//the table is ready to be saved.
		foreach(DataRelation l_parentdatarel 
			in l_dtc.ParentRelations)
				ContainsKey("visited") == false) {
				break ;