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 graphone 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 (dr.ChildTable.TableName)) 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 commitInsertAndUpdate(l_tbl); } //second sweep: delete ar.Reverse(); foreach (DataTable l_tbl in ar) //suppose the commitDeletes method //can find the appropriate datadapter for //the provided DataTable commitDeletes(l_tbl); } //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; l_childrel.ExtendedProperties.Add ("visited",true); DataTable l_dtc = l_childrel.ChildTable; //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) if(l_parentdatarel. ExtendedProperties. ContainsKey("visited") == false) { l_ready=false; break ; } if(l_ready==true) processTable(l_dtc,p_ar); } } |