2 // mcs/class/System.Data/System.Data/XmlDiffLoader.cs
4 // Purpose: Loads XmlDiffGrams to DataSet
6 // class: XmlDiffLoader
7 // assembly: System.Data.dll
8 // namespace: System.Data
11 // Ville Palo <vi64pa@koti.soon.fi>
12 // Lluis Sanchez Gual (lluis@ximian.com)
14 // (c)copyright 2003 Ville Palo
19 using System.Xml.XPath;
20 using System.Collections;
21 using System.Globalization;
23 namespace System.Data {
25 internal class XmlDiffLoader
30 private DataTable table;
31 private Hashtable DiffGrRows = new Hashtable ();
32 private Hashtable ErrorRows = new Hashtable ();
38 public XmlDiffLoader (DataSet DSet)
43 public XmlDiffLoader (DataTable table)
50 #region Public methods
52 public void Load (XmlReader reader)
54 bool origEnforceConstraint = false;
56 origEnforceConstraint = DSet.EnforceConstraints;
57 DSet.EnforceConstraints = false;
60 reader.MoveToContent ();
61 if (reader.IsEmptyElement) return;
63 reader.ReadStartElement ("diffgram", XmlConstants.DiffgrNamespace);
64 reader.MoveToContent ();
66 while (reader.NodeType != XmlNodeType.EndElement)
68 if (reader.NodeType == XmlNodeType.Element)
70 if (reader.LocalName == "before" && reader.NamespaceURI == XmlConstants.DiffgrNamespace)
72 else if (reader.LocalName == "errors" && reader.NamespaceURI == XmlConstants.DiffgrNamespace)
81 reader.ReadEndElement ();
84 DSet.EnforceConstraints = origEnforceConstraint;
87 #endregion // Public methods
89 #region Private methods
91 private void LoadCurrent (XmlReader reader)
93 if (reader.IsEmptyElement) return;
95 reader.ReadStartElement (); // Dataset root
96 reader.MoveToContent ();
98 while (reader.NodeType != XmlNodeType.EndElement)
100 if (reader.NodeType == XmlNodeType.Element)
102 DataTable t = GetTable (reader.LocalName);
104 LoadCurrentTable (t, reader);
106 throw new DataException (Locale.GetText ("Cannot load diffGram. Table '" + reader.LocalName + "' is missing in the destination dataset"));
112 reader.ReadEndElement ();
115 private void LoadBefore (XmlReader reader)
117 if (reader.IsEmptyElement) return;
119 reader.ReadStartElement ();
120 reader.MoveToContent ();
122 while (reader.NodeType != XmlNodeType.EndElement)
124 if (reader.NodeType == XmlNodeType.Element)
126 DataTable t = GetTable (reader.LocalName);
128 LoadBeforeTable(t, reader);
130 throw new DataException (Locale.GetText ("Cannot load diffGram. Table '" + reader.LocalName + "' is missing in the destination dataset"));
136 reader.ReadEndElement ();
140 private void LoadErrors (XmlReader reader)
142 if (reader.IsEmptyElement) return;
144 reader.ReadStartElement ();
145 reader.MoveToContent ();
147 while (reader.NodeType != XmlNodeType.EndElement)
149 if (reader.NodeType == XmlNodeType.Element)
153 // find the row in 'current' section
155 string id = reader.GetAttribute ("id", XmlConstants.DiffgrNamespace);
158 Row = (DataRow) ErrorRows [id];
160 if (reader.IsEmptyElement) continue;
161 reader.ReadStartElement ();
162 while (reader.NodeType != XmlNodeType.EndElement)
164 if (reader.NodeType == XmlNodeType.Element) {
165 string error = reader.GetAttribute ("Error", XmlConstants.DiffgrNamespace);
166 Row.SetColumnError (reader.LocalName, error);
174 reader.ReadEndElement ();
177 private void LoadColumns (DataTable Table, DataRow Row, XmlReader reader, DataRowVersion loadType)
179 if (reader.IsEmptyElement) return;
181 reader.ReadStartElement ();
182 reader.MoveToContent ();
184 while (reader.NodeType != XmlNodeType.EndElement)
186 if (reader.NodeType != XmlNodeType.Element) { reader.Read (); continue; }
188 if (Table.Columns.Contains (reader.LocalName))
190 string colName = reader.LocalName;
191 object data = XmlDataLoader.StringToObject (Table.Columns[colName].DataType, reader.ReadString ());
193 if (loadType == DataRowVersion.Current) Row [colName] = data;
194 else Row.SetOriginalValue (colName, data);
199 DataTable t = GetTable (reader.LocalName);
201 if (loadType == DataRowVersion.Original)
202 LoadBeforeTable (t, reader);
203 else if (loadType == DataRowVersion.Current)
204 LoadCurrentTable (t, reader);
209 reader.ReadEndElement ();
212 private void LoadBeforeTable (DataTable Table, XmlReader reader)
214 string id = reader.GetAttribute ("id", XmlConstants.DiffgrNamespace);
215 string rowOrder = reader.GetAttribute ("rowOrder", XmlConstants.MsdataNamespace);
216 DataRow Row = (DataRow) DiffGrRows [id];
221 Row = Table.NewRow ();
222 LoadColumns (Table, Row, reader, DataRowVersion.Current);
223 Table.Rows.InsertAt (Row, int.Parse (rowOrder));
224 Row.AcceptChanges ();
229 LoadColumns (Table, Row, reader, DataRowVersion.Original);
233 private void LoadCurrentTable (DataTable Table, XmlReader reader)
236 DataRow Row = Table.NewRow ();
238 string id = reader.GetAttribute ("id", XmlConstants.DiffgrNamespace);
239 string error = reader.GetAttribute ("hasErrors");
240 string changes = reader.GetAttribute ("hasChanges", XmlConstants.DiffgrNamespace);
244 if (string.Compare (changes, "modified", true) == 0) {
245 DiffGrRows.Add (id, Row); // for later use
246 state = DataRowState.Modified;
248 else if (string.Compare (changes, "inserted", true) == 0) {
249 state = DataRowState.Added;
252 throw new InvalidOperationException ("Invalid row change state");
255 state = DataRowState.Unchanged;
257 // If row had errors add row to hashtable for later use
258 if (error != null && string.Compare (error, "true", true) == 0)
259 ErrorRows.Add (id, Row);
261 LoadColumns (Table, Row, reader, DataRowVersion.Current);
262 Table.Rows.Add (Row);
264 if (state != DataRowState.Added)
265 Row.AcceptChanges ();
268 DataTable GetTable (string name)
271 return DSet.Tables [name];
272 else if (name == table.TableName)
279 #endregion // Private methods