1 //------------------------------------------------------------------------------
2 // <copyright file="DataSet.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // <owner current="true" primary="true">[....]</owner>
6 // <owner current="true" primary="false">[....]</owner>
7 //------------------------------------------------------------------------------
9 namespace System.Data {
12 using System.Runtime.Serialization;
13 using System.ComponentModel;
14 using System.Diagnostics;
15 using System.Globalization;
17 using System.Collections;
18 using System.Collections.Generic;
19 using System.Collections.Specialized;
21 using System.Xml.Serialization;
23 using System.Xml.Serialization.Advanced;
25 using System.Xml.Schema;
26 using System.Runtime.Serialization.Formatters.Binary; //Binary Formatter
28 using System.CodeDom.Compiler;
29 using System.Configuration;
30 using System.Data.Common;
31 using System.Runtime.Versioning;
32 using System.Runtime.CompilerServices;
36 /// Represents an in-memory cache of data.
40 ResDescriptionAttribute(Res.DataSetDescr),
41 DefaultProperty("DataSetName"),
42 ToolboxItem("Microsoft.VSDesigner.Data.VS.DataSetToolboxItem, " + AssemblyRef.MicrosoftVSDesigner),
43 Designer("Microsoft.VSDesigner.Data.VS.DataSetDesigner, " + AssemblyRef.MicrosoftVSDesigner),
45 XmlSchemaProvider("GetDataSetSchema"),
48 public class DataSet : MarshalByValueComponent, System.ComponentModel.IListSource, IXmlSerializable, ISupportInitializeNotification, ISerializable {
50 private DataViewManager defaultViewManager;
53 private readonly DataTableCollection tableCollection;
54 private readonly DataRelationCollection relationCollection;
55 internal PropertyCollection extendedProperties = null;
56 private string dataSetName = "NewDataSet";
57 private string _datasetPrefix = String.Empty;
58 internal string namespaceURI = string.Empty;
59 private bool enforceConstraints = true;
60 private const String KEY_XMLSCHEMA = "XmlSchema";
61 private const String KEY_XMLDIFFGRAM = "XmlDiffGram";
63 // globalization stuff
64 private bool _caseSensitive;
65 private CultureInfo _culture;
66 private bool _cultureUserSet;
68 // Internal definitions
69 internal bool fInReadXml = false;
70 internal bool fInLoadDiffgram = false;
71 internal bool fTopLevelTable = false;
72 internal bool fInitInProgress = false;
73 internal bool fEnableCascading = true;
74 internal bool fIsSchemaLoading = false;
75 private bool fBoundToDocument; // for XmlDataDocument
78 private PropertyChangedEventHandler onPropertyChangingDelegate;
79 private MergeFailedEventHandler onMergeFailed;
80 private DataRowCreatedEventHandler onDataRowCreated; // Internal for XmlDataDocument only
81 private DataSetClearEventhandler onClearFunctionCalled; // Internal for XmlDataDocument only
82 private System.EventHandler onInitialized;
85 internal readonly static DataTable[] zeroTables = new DataTable[0];
86 internal string mainTableName = "";
88 //default remoting format is XML
89 private SerializationFormat _remotingFormat = SerializationFormat.Xml;
91 private object _defaultViewManagerLock = new Object();
93 private static int _objectTypeCount; // Bid counter
94 private readonly int _objectID = System.Threading.Interlocked.Increment(ref _objectTypeCount);
95 private static XmlSchemaComplexType schemaTypeForWSDL = null;
97 internal bool UseDataSetSchemaOnly; // UseDataSetSchemaOnly , for YUKON
98 internal bool UdtIsWrapped; // if UDT is wrapped , for YUKON
101 /// <para>Initializes a new instance of the <see cref='System.Data.DataSet'/> class.</para>
104 GC.SuppressFinalize(this);
105 Bid.Trace("<ds.DataSet.DataSet|API> %d#\n", ObjectID); // others will call this constr
106 // Set default locale
107 this.tableCollection = new DataTableCollection(this);
108 this.relationCollection = new DataRelationCollection.DataSetRelationCollection(this);
109 _culture = CultureInfo.CurrentCulture; // Set default locale
113 /// <para>Initializes a new instance of a <see cref='System.Data.DataSet'/>
114 /// class with the given name.</para>
116 public DataSet(string dataSetName)
119 this.DataSetName = dataSetName;
123 DefaultValue(SerializationFormat.Xml)
125 public SerializationFormat RemotingFormat {
127 return _remotingFormat;
130 if (value != SerializationFormat.Binary && value != SerializationFormat.Xml) {
131 throw ExceptionBuilder.InvalidRemotingFormat(value);
133 _remotingFormat = value;
134 // this property is inherited to DataTable from DataSet.So we set this value to DataTable also
135 for (int i = 0; i < Tables.Count; i++) {
136 Tables[i].RemotingFormat = value;
141 [BrowsableAttribute(false)]
142 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
143 public virtual SchemaSerializationMode SchemaSerializationMode { //Typed DataSet calls into this
145 return SchemaSerializationMode.IncludeSchema;
148 if (value != SchemaSerializationMode.IncludeSchema) {
149 throw ExceptionBuilder.CannotChangeSchemaSerializationMode();
154 // Check whether the stream is binary serialized.
155 // 'static' function that consumes SerializationInfo
156 protected bool IsBinarySerialized(SerializationInfo info, StreamingContext context) {// mainly for typed DS
157 // our default remoting format is XML
158 SerializationFormat remotingFormat = SerializationFormat.Xml;
159 SerializationInfoEnumerator e = info.GetEnumerator();
161 while (e.MoveNext()) {
162 if (e.Name == "DataSet.RemotingFormat") {//DataSet.RemotingFormat does not exist in V1/V1.1 versions
163 remotingFormat = (SerializationFormat)e.Value;
167 return (remotingFormat == SerializationFormat.Binary);
170 // Should Schema be included during Serialization
171 // 'static' function that consumes SerializationInfo
172 protected SchemaSerializationMode DetermineSchemaSerializationMode(SerializationInfo info, StreamingContext context) { //Typed DataSet calls into this
173 SchemaSerializationMode schemaSerializationMode = SchemaSerializationMode.IncludeSchema;
174 SerializationInfoEnumerator e = info.GetEnumerator();
176 while (e.MoveNext()) {
177 if (e.Name == "SchemaSerializationMode.DataSet") { //SchemaSerializationMode.DataSet does not exist in V1/V1.1 versions
178 schemaSerializationMode = (SchemaSerializationMode)e.Value;
182 return schemaSerializationMode;
185 protected SchemaSerializationMode DetermineSchemaSerializationMode(XmlReader reader) { //Typed DataSet calls into this
186 SchemaSerializationMode schemaSerializationMode = SchemaSerializationMode.IncludeSchema;
187 reader.MoveToContent();
188 if (reader.NodeType == XmlNodeType.Element) {
189 if (reader.HasAttributes) {
190 string attribValue = reader.GetAttribute(Keywords.MSD_SCHEMASERIALIZATIONMODE, Keywords.MSDNS);
191 if ((String.Compare(attribValue, Keywords.MSD_EXCLUDESCHEMA, StringComparison.OrdinalIgnoreCase) == 0)) {
192 schemaSerializationMode = SchemaSerializationMode.ExcludeSchema;
194 else if ((String.Compare(attribValue, Keywords.MSD_INCLUDESCHEMA, StringComparison.OrdinalIgnoreCase) == 0)) {
195 schemaSerializationMode = SchemaSerializationMode.IncludeSchema;
197 else if (attribValue != null) { // if attrib does not exist, then don't throw
198 throw ExceptionBuilder.InvalidSchemaSerializationMode(typeof(SchemaSerializationMode), attribValue);
202 return schemaSerializationMode;
206 // Deserialize all the tables data of the dataset from binary/xml stream.
207 // 'instance' method that consumes SerializationInfo
208 protected void GetSerializationData(SerializationInfo info, StreamingContext context) {// mainly for typed DS
209 SerializationFormat remotingFormat = SerializationFormat.Xml;
210 SerializationInfoEnumerator e = info.GetEnumerator();
212 while (e.MoveNext()) {
213 if (e.Name == "DataSet.RemotingFormat") { //DataSet.RemotingFormat does not exist in V1/V1.1 versions
214 remotingFormat = (SerializationFormat)e.Value;
218 DeserializeDataSetData(info, context, remotingFormat);
222 // Deserialize all the tables schema and data of the dataset from binary/xml stream.
223 protected DataSet(SerializationInfo info, StreamingContext context)
224 : this(info, context, true) {
226 protected DataSet(SerializationInfo info, StreamingContext context, bool ConstructSchema)
228 SerializationFormat remotingFormat = SerializationFormat.Xml;
229 SchemaSerializationMode schemaSerializationMode = SchemaSerializationMode.IncludeSchema;
230 SerializationInfoEnumerator e = info.GetEnumerator();
232 while (e.MoveNext()) {
234 case "DataSet.RemotingFormat": //DataSet.RemotingFormat does not exist in V1/V1.1 versions
235 remotingFormat = (SerializationFormat)e.Value;
237 case "SchemaSerializationMode.DataSet": //SchemaSerializationMode.DataSet does not exist in V1/V1.1 versions
238 schemaSerializationMode = (SchemaSerializationMode)e.Value;
243 if (schemaSerializationMode == SchemaSerializationMode.ExcludeSchema) {
244 InitializeDerivedDataSet();
247 // adding back this check will fix typed dataset XML remoting, but we have to fix case that
248 // a class inherits from DataSet and just relies on DataSet to deserialize (see SQL BU DT 374717)
249 // to fix that case also, we need to add a flag and add it to below check so return (no-op) will be
250 // conditional (flag needs to be set in TypedDataSet
251 if (remotingFormat == SerializationFormat.Xml && !ConstructSchema /* && this.GetType() != typeof(DataSet)*/) {
252 return; //For typed dataset xml remoting, this is a no-op
254 DeserializeDataSet(info, context, remotingFormat, schemaSerializationMode);
259 [System.Security.Permissions.SecurityPermissionAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Flags = System.Security.Permissions.SecurityPermissionFlag.SerializationFormatter)]
260 public virtual void GetObjectData(SerializationInfo info, StreamingContext context) {
261 SerializationFormat remotingFormat = RemotingFormat;
262 SerializeDataSet(info, context, remotingFormat);
265 // Deserialize all the tables data of the dataset from binary/xml stream.
266 protected virtual void InitializeDerivedDataSet() {
270 // Serialize all the tables.
271 private void SerializeDataSet(SerializationInfo info, StreamingContext context, SerializationFormat remotingFormat) {
272 Debug.Assert(info != null);
273 info.AddValue("DataSet.RemotingVersion", new Version(2, 0));
275 // SqlHotFix 299, SerializationFormat enumeration types don't exist in V1.1 SP1
276 if (SerializationFormat.Xml != remotingFormat) {
277 info.AddValue("DataSet.RemotingFormat", remotingFormat);
280 // SqlHotFix 299, SchemaSerializationMode enumeration types don't exist in V1.1 SP1
281 if (SchemaSerializationMode.IncludeSchema != SchemaSerializationMode) {
282 //SkipSchemaDuringSerialization
283 info.AddValue("SchemaSerializationMode.DataSet", SchemaSerializationMode);
286 if (remotingFormat != SerializationFormat.Xml) {
287 if (SchemaSerializationMode == SchemaSerializationMode.IncludeSchema) {
289 //DataSet public state properties
290 SerializeDataSetProperties(info, context);
293 info.AddValue("DataSet.Tables.Count", Tables.Count);
295 //Tables, Columns, Rows
296 for (int i = 0; i < Tables.Count; i++) {
297 BinaryFormatter bf = new BinaryFormatter(null, new StreamingContext(context.State, false));
298 MemoryStream memStream = new MemoryStream();
299 bf.Serialize(memStream, Tables[i]);
300 memStream.Position = 0;
301 info.AddValue(String.Format(CultureInfo.InvariantCulture, "DataSet.Tables_{0}", i), memStream.GetBuffer());
305 for (int i = 0; i < Tables.Count; i++) {
306 Tables[i].SerializeConstraints(info, context, i, true);
310 SerializeRelations(info, context);
313 for (int i = 0; i < Tables.Count; i++) {
314 Tables[i].SerializeExpressionColumns(info, context, i);
318 //Serialize DataSet public properties.
319 SerializeDataSetProperties(info, context);
322 for (int i = 0; i < Tables.Count; i++) {
323 Tables[i].SerializeTableData(info, context, i);
325 } else { // old behaviour
327 String strSchema = this.GetXmlSchemaForRemoting(null);
329 String strData = null;
330 info.AddValue(KEY_XMLSCHEMA, strSchema);
332 StringBuilder strBuilder;
333 strBuilder = new StringBuilder(EstimatedXmlStringSize() * 2);
334 StringWriter strWriter = new StringWriter(strBuilder, CultureInfo.InvariantCulture);
335 XmlTextWriter w = new XmlTextWriter(strWriter);
336 WriteXml(w, XmlWriteMode.DiffGram);
337 strData = strWriter.ToString();
338 info.AddValue(KEY_XMLDIFFGRAM, strData);
342 // Deserialize all the tables - marked internal so that DataTable can call into this
343 internal void DeserializeDataSet(SerializationInfo info, StreamingContext context, SerializationFormat remotingFormat, SchemaSerializationMode schemaSerializationMode) {
344 // deserialize schema
345 DeserializeDataSetSchema(info, context, remotingFormat, schemaSerializationMode);
347 DeserializeDataSetData(info, context, remotingFormat);
350 // Deserialize schema.
351 private void DeserializeDataSetSchema(SerializationInfo info, StreamingContext context, SerializationFormat remotingFormat, SchemaSerializationMode schemaSerializationMode) {
352 if (remotingFormat != SerializationFormat.Xml) {
353 if (schemaSerializationMode == SchemaSerializationMode.IncludeSchema) {
354 //DataSet public state properties
355 DeserializeDataSetProperties(info, context);
358 int tableCount = info.GetInt32("DataSet.Tables.Count");
360 //Tables, Columns, Rows
361 for (int i = 0; i < tableCount; i++) {
362 Byte[] buffer = (Byte[])info.GetValue(String.Format(CultureInfo.InvariantCulture, "DataSet.Tables_{0}", i), typeof(Byte[]));
363 MemoryStream memStream = new MemoryStream(buffer);
364 memStream.Position = 0;
365 BinaryFormatter bf = new BinaryFormatter(null, new StreamingContext(context.State, false));
366 DataTable dt = (DataTable)bf.Deserialize(memStream);
371 for (int i = 0; i < tableCount; i++) {
372 Tables[i].DeserializeConstraints(info, context, /* table index */i, /* serialize all constraints */ true); //
376 DeserializeRelations(info, context);
379 for (int i = 0; i < tableCount; i++) {
380 Tables[i].DeserializeExpressionColumns(info, context, i);
383 //DeSerialize DataSet public properties.[Locale, CaseSensitive and EnforceConstraints]
384 DeserializeDataSetProperties(info, context);
387 string strSchema = (String)info.GetValue(KEY_XMLSCHEMA, typeof(System.String));
389 if (strSchema != null) {
390 this.ReadXmlSchema(new XmlTextReader(new StringReader(strSchema)), true);
395 // Deserialize all data.
396 private void DeserializeDataSetData(SerializationInfo info, StreamingContext context, SerializationFormat remotingFormat) {
397 if (remotingFormat != SerializationFormat.Xml) {
398 for (int i = 0; i < Tables.Count; i++) {
399 Tables[i].DeserializeTableData(info, context, i);
403 string strData = (String)info.GetValue(KEY_XMLDIFFGRAM, typeof(System.String));
405 if (strData != null) {
406 this.ReadXml(new XmlTextReader(new StringReader(strData)), XmlReadMode.DiffGram);
411 // Serialize just the dataset properties
412 private void SerializeDataSetProperties(SerializationInfo info, StreamingContext context) {
413 //DataSet basic properties
414 info.AddValue("DataSet.DataSetName", DataSetName);
415 info.AddValue("DataSet.Namespace", Namespace);
416 info.AddValue("DataSet.Prefix", Prefix);
417 //DataSet runtime properties
418 info.AddValue("DataSet.CaseSensitive", CaseSensitive);
419 info.AddValue("DataSet.LocaleLCID", Locale.LCID);
420 info.AddValue("DataSet.EnforceConstraints", EnforceConstraints);
423 info.AddValue("DataSet.ExtendedProperties", ExtendedProperties);
426 // DeSerialize dataset properties
427 private void DeserializeDataSetProperties(SerializationInfo info, StreamingContext context) {
428 //DataSet basic properties
429 dataSetName = info.GetString("DataSet.DataSetName");
430 namespaceURI = info.GetString("DataSet.Namespace");
431 _datasetPrefix = info.GetString("DataSet.Prefix");
432 //DataSet runtime properties
433 _caseSensitive = info.GetBoolean("DataSet.CaseSensitive");
434 int lcid = (int)info.GetValue("DataSet.LocaleLCID", typeof(int));
435 _culture = new CultureInfo(lcid);
436 _cultureUserSet = true;
437 enforceConstraints = info.GetBoolean("DataSet.EnforceConstraints");
442 extendedProperties = (PropertyCollection)info.GetValue("DataSet.ExtendedProperties", typeof(PropertyCollection));
445 // Gets relation info from the dataset.
446 // ***Schema for Serializing ArrayList of Relations***
447 // Relations -> [relationName]->[parentTableIndex, parentcolumnIndexes]->[childTableIndex, childColumnIndexes]->[Nested]->[extendedProperties]
448 private void SerializeRelations(SerializationInfo info, StreamingContext context) {
449 ArrayList relationList = new ArrayList();
451 foreach (DataRelation rel in Relations) {
452 int[] parentInfo = new int[rel.ParentColumns.Length + 1];
454 parentInfo[0] = Tables.IndexOf(rel.ParentTable);
455 for (int j = 1; j < parentInfo.Length; j++) {
456 parentInfo[j] = rel.ParentColumns[j - 1].Ordinal;
459 int[] childInfo = new int[rel.ChildColumns.Length + 1];
460 childInfo[0] = Tables.IndexOf(rel.ChildTable);
461 for (int j = 1; j < childInfo.Length; j++) {
462 childInfo[j] = rel.ChildColumns[j - 1].Ordinal;
465 ArrayList list = new ArrayList();
466 list.Add(rel.RelationName);
467 list.Add(parentInfo);
469 list.Add(rel.Nested);
470 list.Add(rel.extendedProperties);
472 relationList.Add(list);
474 info.AddValue("DataSet.Relations", relationList);
478 Adds relations to the dataset.
479 ***Schema for Serializing ArrayList of Relations***
480 Relations -> [relationName]->[parentTableIndex, parentcolumnIndexes]->[childTableIndex, childColumnIndexes]->[Nested]->[extendedProperties]
482 private void DeserializeRelations(SerializationInfo info, StreamingContext context) {
483 ArrayList relationList = (ArrayList)info.GetValue("DataSet.Relations", typeof(ArrayList));
485 foreach (ArrayList list in relationList) {
486 string relationName = (string)list[0];
487 int[] parentInfo = (int[])list[1];
488 int[] childInfo = (int[])list[2];
489 bool isNested = (bool)list[3];
490 PropertyCollection extendedProperties = (PropertyCollection)list[4];
493 DataColumn[] parentkeyColumns = new DataColumn[parentInfo.Length - 1];
494 for (int i = 0; i < parentkeyColumns.Length; i++) {
495 parentkeyColumns[i] = Tables[parentInfo[0]].Columns[parentInfo[i + 1]];
499 DataColumn[] childkeyColumns = new DataColumn[childInfo.Length - 1];
500 for (int i = 0; i < childkeyColumns.Length; i++) {
501 childkeyColumns[i] = Tables[childInfo[0]].Columns[childInfo[i + 1]];
504 //Create the Relation, without any constraints[Assumption: The constraints are added earlier than the relations]
505 DataRelation rel = new DataRelation(relationName, parentkeyColumns, childkeyColumns, false);
506 rel.CheckMultipleNested = false; // disable the check for multiple nested parent
507 rel.Nested = isNested;
508 rel.extendedProperties = extendedProperties;
511 rel.CheckMultipleNested = true; // enable the check for multiple nested parent
515 internal void FailedEnableConstraints() {
516 this.EnforceConstraints = false;
517 throw ExceptionBuilder.EnforceConstraint();
522 /// Gets or sets a value indicating whether string
523 /// comparisons within <see cref='System.Data.DataTable'/>
529 ResCategoryAttribute(Res.DataCategory_Data),
531 ResDescriptionAttribute(Res.DataSetCaseSensitiveDescr)
533 public bool CaseSensitive {
535 return _caseSensitive;
538 if (_caseSensitive != value)
540 bool oldValue = _caseSensitive;
541 _caseSensitive = value;
543 if (!ValidateCaseConstraint()) {
544 _caseSensitive = oldValue;
545 throw ExceptionBuilder.CannotChangeCaseLocale();
548 foreach (DataTable table in Tables) {
549 table.SetCaseSensitiveValue(value, false, true);
555 bool System.ComponentModel.IListSource.ContainsListCollection {
562 /// <para>Gets a custom view of the data contained by the <see cref='System.Data.DataSet'/> , one
563 /// that allows filtering, searching, and navigating through the custom data view.</para>
565 [Browsable(false), ResDescriptionAttribute(Res.DataSetDefaultViewDescr)]
566 public DataViewManager DefaultViewManager {
568 if (defaultViewManager == null) {
569 lock (_defaultViewManagerLock) {
570 if (defaultViewManager == null) {
571 defaultViewManager = new DataViewManager(this, true);
575 return defaultViewManager;
580 /// <para>Gets or sets a value indicating whether constraint rules are followed when
581 /// attempting any update operation.</para>
583 [DefaultValue(true), ResDescriptionAttribute(Res.DataSetEnforceConstraintsDescr)]
584 public bool EnforceConstraints {
586 return enforceConstraints;
590 Bid.ScopeEnter(out hscp, "<ds.DataSet.set_EnforceConstraints|API> %d#, %d{bool}\n", ObjectID, value);
592 if (this.enforceConstraints != value) {
595 this.enforceConstraints = value;
599 Bid.ScopeLeave(ref hscp);
604 internal void RestoreEnforceConstraints(bool value) {
605 this.enforceConstraints = value;
608 internal void EnableConstraints()
611 Bid.ScopeEnter(out hscp, "<ds.DataSet.EnableConstraints|INFO> %d#\n", ObjectID);
614 for (ConstraintEnumerator constraints = new ConstraintEnumerator(this); constraints.GetNext(); ) {
615 Constraint constraint = (Constraint)constraints.GetConstraint();
616 errors |= constraint.IsConstraintViolated();
619 foreach (DataTable table in Tables) {
620 foreach (DataColumn column in table.Columns) {
621 if (!column.AllowDBNull) {
622 errors |= column.IsNotAllowDBNullViolated();
624 if (column.MaxLength >= 0) {
625 errors |= column.IsMaxLengthViolated();
631 this.FailedEnableConstraints();
634 Bid.ScopeLeave(ref hscp);
640 /// sets the name of this <see cref='System.Data.DataSet'/> .</para>
643 ResCategoryAttribute(Res.DataCategory_Data),
645 ResDescriptionAttribute(Res.DataSetDataSetNameDescr)
647 public string DataSetName {
652 Bid.Trace("<ds.DataSet.set_DataSetName|API> %d#, '%ls'\n", ObjectID, value);
653 if (value != dataSetName) {
654 if (value == null || value.Length == 0)
655 throw ExceptionBuilder.SetDataSetNameToEmpty();
656 DataTable conflicting = Tables[value, Namespace];
657 if ((conflicting != null) && (!conflicting.fNestedInDataset))
658 throw ExceptionBuilder.SetDataSetNameConflicting(value);
659 RaisePropertyChanging("DataSetName");
660 this.dataSetName = value;
669 ResCategoryAttribute(Res.DataCategory_Data),
670 ResDescriptionAttribute(Res.DataSetNamespaceDescr)
672 public string Namespace {
677 Bid.Trace("<ds.DataSet.set_Namespace|API> %d#, '%ls'\n", ObjectID, value);
679 value = String.Empty;
680 if (value != namespaceURI) {
681 RaisePropertyChanging("Namespace");
682 foreach (DataTable dt in Tables) {
683 if (dt.tableNamespace != null)
685 if ((dt.NestedParentRelations.Length == 0) ||
686 (dt.NestedParentRelations.Length == 1 && dt.NestedParentRelations[0].ChildTable == dt)) {
687 // dt.SelfNestedWithOneRelation) { // this is wrong bug it was previous behavior
688 if (Tables.Contains(dt.TableName, value, false, true))
689 throw ExceptionBuilder.DuplicateTableName2(dt.TableName, value);
690 dt.CheckCascadingNamespaceConflict(value);
691 dt.DoRaiseNamespaceChange();
694 namespaceURI = value;
697 if (Common.ADP.IsEmpty(value))
698 _datasetPrefix = String.Empty;
704 /// <para>[To be supplied.]</para>
708 ResCategoryAttribute(Res.DataCategory_Data),
709 ResDescriptionAttribute(Res.DataSetPrefixDescr)
711 public string Prefix {
712 get { return _datasetPrefix; }
715 value = String.Empty;
717 if ((XmlConvert.DecodeName(value) == value) &&
718 (XmlConvert.EncodeName(value) != value))
719 throw ExceptionBuilder.InvalidPrefix(value);
722 if (value != _datasetPrefix) {
723 RaisePropertyChanging("Prefix");
724 _datasetPrefix = value;
730 /// <para>Gets the collection of custom user information.</para>
733 ResCategoryAttribute(Res.DataCategory_Data),
735 ResDescriptionAttribute(Res.ExtendedPropertiesDescr)
737 public PropertyCollection ExtendedProperties {
739 if (extendedProperties == null) {
740 extendedProperties = new PropertyCollection();
742 return extendedProperties;
748 /// Gets a value indicating whether there are errors in any
749 /// of the rows in any of the tables of this <see cref='System.Data.DataSet'/> .
752 [Browsable(false), ResDescriptionAttribute(Res.DataSetHasErrorsDescr)]
753 public bool HasErrors {
755 for (int i = 0; i < Tables.Count; i++) {
756 if (Tables[i].HasErrors)
764 public bool IsInitialized {
766 return !fInitInProgress;
772 /// Gets or sets the locale information used to compare strings within the table.
776 ResCategoryAttribute(Res.DataCategory_Data),
777 ResDescriptionAttribute(Res.DataSetLocaleDescr)
779 public CultureInfo Locale {
781 // used for comparing not formating/parsing
782 Debug.Assert(null != _culture, "DataSet.Locale: null culture");
787 Bid.ScopeEnter(out hscp, "<ds.DataSet.set_Locale|API> %d#\n", ObjectID);
790 if (!_culture.Equals(value)) {
791 SetLocaleValue(value, true);
793 _cultureUserSet = true;
797 Bid.ScopeLeave(ref hscp);
802 internal void SetLocaleValue(CultureInfo value, bool userSet) {
804 bool exceptionThrown = false;
807 CultureInfo oldLocale = _culture;
808 bool oldUserSet = _cultureUserSet;
812 _cultureUserSet = userSet;
814 foreach (DataTable table in Tables) {
815 if (!table.ShouldSerializeLocale()) {
816 bool retchk = table.SetLocaleValue(value, false, false);
817 //Debug.Assert(retchk == table.ShouldSerializeLocale(), "unexpected setting of table locale"); may fire with Deserialize
821 flag = ValidateLocaleConstraint();
824 foreach (DataTable table in Tables) {
826 if (!table.ShouldSerializeLocale()) {
827 table.SetLocaleValue(value, false, true);
834 exceptionThrown = true;
838 if (!flag) { // reset old locale if ValidationFailed or exception thrown
839 _culture = oldLocale;
840 _cultureUserSet = oldUserSet;
841 foreach (DataTable table in Tables) {
842 if (!table.ShouldSerializeLocale()) {
843 table.SetLocaleValue(oldLocale, false, false);
847 for (int i = 0; i < tableCount; ++i) {
848 if (!Tables[i].ShouldSerializeLocale()) {
849 Tables[i].SetLocaleValue(oldLocale, false, true);
853 catch (Exception e) {
854 if (!Common.ADP.IsCatchableExceptionType(e)) {
857 Common.ADP.TraceExceptionWithoutRethrow(e);
859 if (!exceptionThrown) {
860 throw ExceptionBuilder.CannotChangeCaseLocale(null);
866 internal bool ShouldSerializeLocale() {
867 // this method is used design-time scenarios via reflection
868 // by the property grid to show the Locale property in bold or not
869 // by the code dom for persisting the Locale property or not
871 // we always want the locale persisted if set by user or different the current thread
872 // but that logic should by performed by the serializion code
873 return _cultureUserSet;
877 /// <para>[To be supplied.]</para>
879 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
880 public override ISite Site {
885 ISite oldSite = Site;
886 if (value == null && oldSite != null) {
887 IContainer cont = oldSite.Container;
890 for (int i = 0; i < Tables.Count; i++) {
891 if (Tables[i].Site != null) {
892 cont.Remove(Tables[i]);
905 /// Get the collection of relations that link tables and
906 /// allow navigation from parent tables to child tables.
910 DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
911 ResCategoryAttribute(Res.DataCategory_Data),
912 ResDescriptionAttribute(Res.DataSetRelationsDescr)
914 public DataRelationCollection Relations {
916 return relationCollection;
922 /// Indicates whether <see cref='Relations'/> property should be persisted.
925 protected virtual bool ShouldSerializeRelations() {
926 return true; /*Relations.Count > 0;*/ // VS7 300569
931 /// Resets the <see cref='System.Data.DataSet.Relations'/> property to its default state.
934 private void ResetRelations()
940 /// <para>Gets the collection of tables contained in the <see cref='System.Data.DataSet'/>.</para>
943 DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
944 ResCategoryAttribute(Res.DataCategory_Data),
945 ResDescriptionAttribute(Res.DataSetTablesDescr)
947 public DataTableCollection Tables {
949 return tableCollection;
955 /// Indicates whether <see cref='System.Data.DataSet.Tables'/> property should be persisted.
958 protected virtual bool ShouldSerializeTables() {
959 return true;/*(Tables.Count > 0);*/ // VS7 300569
964 /// Resets the <see cref='System.Data.DataSet.Tables'/> property to its default state.
967 private void ResetTables()
972 internal bool FBoundToDocument {
974 return fBoundToDocument;
977 fBoundToDocument = value;
983 /// Commits all the changes made to this <see cref='System.Data.DataSet'/> since it was loaded or the last
984 /// time <see cref='System.Data.DataSet.AcceptChanges'/> was called.
987 public void AcceptChanges()
990 Bid.ScopeEnter(out hscp, "<ds.DataSet.AcceptChanges|API> %d#\n", ObjectID);
992 for (int i = 0; i < Tables.Count; i++)
993 Tables[i].AcceptChanges();
996 Bid.ScopeLeave(ref hscp);
1000 internal event PropertyChangedEventHandler PropertyChanging {
1002 onPropertyChangingDelegate += value;
1005 onPropertyChangingDelegate -= value;
1010 /// <para>Occurs when attempting to merge schemas for two tables with the same
1014 ResCategoryAttribute(Res.DataCategory_Action),
1015 ResDescriptionAttribute(Res.DataSetMergeFailedDescr)
1017 public event MergeFailedEventHandler MergeFailed {
1019 onMergeFailed += value;
1022 onMergeFailed -= value;
1026 internal event DataRowCreatedEventHandler DataRowCreated {
1028 onDataRowCreated += value;
1031 onDataRowCreated -= value;
1035 internal event DataSetClearEventhandler ClearFunctionCalled {
1037 onClearFunctionCalled += value;
1040 onClearFunctionCalled -= value;
1045 ResCategoryAttribute(Res.DataCategory_Action),
1046 ResDescriptionAttribute(Res.DataSetInitializedDescr)
1048 public event System.EventHandler Initialized {
1050 onInitialized += value;
1053 onInitialized -= value;
1057 public void BeginInit() {
1058 fInitInProgress = true;
1061 public void EndInit() {
1062 Tables.FinishInitCollection();
1063 for (int i = 0; i < Tables.Count; i++) {
1064 Tables[i].Columns.FinishInitCollection();
1067 for (int i = 0; i < Tables.Count; i++) {
1068 Tables[i].Constraints.FinishInitConstraints();
1071 ((DataRelationCollection.DataSetRelationCollection)Relations).FinishInitRelations();
1073 fInitInProgress = false;
1078 /// <para>Clears the <see cref='System.Data.DataSet'/> of any data by removing all rows in all tables.</para>
1083 Bid.ScopeEnter(out hscp, "<ds.DataSet.Clear|API> %d#\n", ObjectID);
1085 OnClearFunctionCalled(null);
1086 bool fEnforce = EnforceConstraints;
1087 EnforceConstraints = false;
1088 for (int i = 0; i < Tables.Count; i++)
1090 EnforceConstraints = fEnforce;
1093 Bid.ScopeLeave(ref hscp);
1098 /// <para>Clones the structure of the <see cref='System.Data.DataSet'/>, including all <see cref='System.Data.DataTable'/> schemas, relations, and
1099 /// constraints.</para>
1101 // Prevent inlining so that reflection calls are not moved to caller that may be in a different assembly that may have a different grant set.
1102 [MethodImpl(MethodImplOptions.NoInlining)]
1103 public virtual DataSet Clone() {
1105 Bid.ScopeEnter(out hscp, "<ds.DataSet.Clone|API> %d#\n", ObjectID);
1107 DataSet ds = (DataSet)Activator.CreateInstance(this.GetType(), true);
1109 if (ds.Tables.Count > 0) // [....] : To clean up all the schema in strong typed dataset.
1112 //copy some original dataset properties
1113 ds.DataSetName = DataSetName;
1114 ds.CaseSensitive = CaseSensitive;
1115 ds._culture = _culture;
1116 ds._cultureUserSet = _cultureUserSet;
1117 ds.EnforceConstraints = EnforceConstraints;
1118 ds.Namespace = Namespace;
1120 ds.RemotingFormat = RemotingFormat;
1121 ds.fIsSchemaLoading = true; //delay expression evaluation
1125 DataTableCollection tbls = Tables;
1126 for (int i = 0; i < tbls.Count; i++) {
1127 DataTable dt = tbls[i].Clone(ds);
1128 dt.tableNamespace = tbls[i].Namespace; // hardcode the namespace for a second to not mess up
1129 // DataRelation cloning.
1133 // ...Constraints...
1134 for (int i = 0; i < tbls.Count; i++) {
1135 ConstraintCollection constraints = tbls[i].Constraints;
1136 for (int j = 0; j < constraints.Count; j++) {
1137 if (constraints[j] is UniqueConstraint)
1139 ForeignKeyConstraint foreign = constraints[j] as ForeignKeyConstraint;
1140 if (foreign.Table == foreign.RelatedTable)
1141 continue;// we have already added this foreign key in while cloning the datatable
1142 ds.Tables[i].Constraints.Add(constraints[j].Clone(ds));
1147 DataRelationCollection rels = Relations;
1148 for (int i = 0; i < rels.Count; i++) {
1149 DataRelation rel = rels[i].Clone(ds);
1150 rel.CheckMultipleNested = false; // disable the check for multiple nested parent
1151 ds.Relations.Add(rel);
1152 rel.CheckMultipleNested = true; // enable the check for multiple nested parent
1155 // ...Extended Properties...
1156 if (this.extendedProperties != null) {
1157 foreach (Object key in this.extendedProperties.Keys) {
1158 ds.ExtendedProperties[key] = this.extendedProperties[key];
1162 foreach (DataTable table in Tables)
1163 foreach (DataColumn col in table.Columns)
1164 if (col.Expression.Length != 0)
1165 ds.Tables[table.TableName, table.Namespace].Columns[col.ColumnName].Expression = col.Expression;
1167 for (int i = 0; i < tbls.Count; i++) {
1168 ds.Tables[i].tableNamespace = tbls[i].tableNamespace; // undo the hardcoding of the namespace
1171 ds.fIsSchemaLoading = false; //reactivate column computations
1176 Bid.ScopeLeave(ref hscp);
1181 /// <para>Copies both the structure and data for this <see cref='System.Data.DataSet'/>.</para>
1183 public DataSet Copy()
1186 Bid.ScopeEnter(out hscp, "<ds.DataSet.Copy|API> %d#\n", ObjectID);
1188 DataSet dsNew = Clone();
1189 bool fEnforceConstraints = dsNew.EnforceConstraints;
1190 dsNew.EnforceConstraints = false;
1191 foreach (DataTable table in this.Tables)
1193 DataTable destTable = dsNew.Tables[table.TableName, table.Namespace];
1195 foreach (DataRow row in table.Rows)
1196 table.CopyRow(destTable, row);
1199 dsNew.EnforceConstraints = fEnforceConstraints;
1204 Bid.ScopeLeave(ref hscp);
1208 internal Int32 EstimatedXmlStringSize()
1211 for (int i = 0; i < Tables.Count; i++) {
1212 Int32 rowBytes = (Tables[i].TableName.Length + 4) << 2;
1213 DataTable table = Tables[i];
1214 for (int j = 0; j < table.Columns.Count; j++) {
1215 rowBytes += ((table.Columns[j].ColumnName.Length + 4) << 2);
1218 bytes += table.Rows.Count * rowBytes;
1225 /// <para>Returns a copy of the <see cref='System.Data.DataSet'/> that contains all changes made to
1226 /// it since it was loaded or <see cref='System.Data.DataSet.AcceptChanges'/>
1227 /// was last called.</para>
1229 public DataSet GetChanges()
1231 return GetChanges(DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);
1234 private struct TableChanges {
1235 private BitArray _rowChanges;
1236 private int _hasChanges;
1238 internal TableChanges(int rowCount) {
1239 _rowChanges = new BitArray(rowCount);
1242 internal int HasChanges {
1243 get { return _hasChanges; }
1244 set { _hasChanges = value; }
1246 internal bool this[int index] {
1247 get { return _rowChanges[index]; }
1249 Debug.Assert(value && !_rowChanges[index], "setting twice or to false");
1250 _rowChanges[index] = value;
1256 public DataSet GetChanges(DataRowState rowStates)
1259 Bid.ScopeEnter(out hscp, "<ds.DataSet.GetChanges|API> %d#, rowStates=%d{ds.DataRowState}\n", ObjectID, (int)rowStates);
1261 DataSet dsNew = null;
1262 bool fEnforceConstraints = false;
1263 if (0 != (rowStates & ~(DataRowState.Added | DataRowState.Deleted | DataRowState.Modified | DataRowState.Unchanged))) {
1264 throw ExceptionBuilder.InvalidRowState(rowStates);
1267 // Initialize all the individual table bitmaps.
1268 TableChanges[] bitMatrix = new TableChanges[Tables.Count];
1269 for (int i = 0; i < bitMatrix.Length; ++i) {
1270 bitMatrix[i] = new TableChanges(Tables[i].Rows.Count);
1273 // find all the modified rows and their parents
1274 MarkModifiedRows(bitMatrix, rowStates);
1276 // copy the changes to a cloned table
1277 for (int i = 0; i < bitMatrix.Length; ++i) {
1278 Debug.Assert(0 <= bitMatrix[i].HasChanges, "negative change count");
1279 if (0 < bitMatrix[i].HasChanges) {
1280 if (null == dsNew) {
1281 dsNew = this.Clone();
1282 fEnforceConstraints = dsNew.EnforceConstraints;
1283 dsNew.EnforceConstraints = false;
1286 DataTable table = this.Tables[i];
1287 DataTable destTable = dsNew.Tables[table.TableName, table.Namespace];
1288 Debug.Assert(bitMatrix[i].HasChanges <= table.Rows.Count, "to many changes");
1290 for (int j = 0; 0 < bitMatrix[i].HasChanges; ++j) { // Loop through the rows.
1291 if (bitMatrix[i][j]) {
1292 table.CopyRow(destTable, table.Rows[j]);
1293 bitMatrix[i].HasChanges--;
1299 if (null != dsNew) {
1300 dsNew.EnforceConstraints = fEnforceConstraints;
1305 Bid.ScopeLeave(ref hscp);
1309 private void MarkModifiedRows(TableChanges[] bitMatrix, DataRowState rowStates) {
1310 // for every table, every row & every relation find the modified rows and for non-deleted rows, their parents
1311 for (int tableIndex = 0; tableIndex < bitMatrix.Length; ++tableIndex) {
1312 DataRowCollection rows = Tables[tableIndex].Rows;
1313 int rowCount = rows.Count;
1315 for (int rowIndex = 0; rowIndex < rowCount; ++rowIndex) {
1316 DataRow row = rows[rowIndex];
1317 DataRowState rowState = row.RowState;
1318 Debug.Assert(DataRowState.Added == rowState ||
1319 DataRowState.Deleted == rowState ||
1320 DataRowState.Modified == rowState ||
1321 DataRowState.Unchanged == rowState,
1322 "unexpected DataRowState");
1324 // if bit not already set and row is modified
1325 if ((0 != (rowStates & rowState)) && !bitMatrix[tableIndex][rowIndex]) {
1326 bitMatrix[tableIndex][rowIndex] = true;
1328 if (DataRowState.Deleted != rowState) {
1329 MarkRelatedRowsAsModified(bitMatrix, row);
1336 private void MarkRelatedRowsAsModified(TableChanges[] bitMatrix, DataRow row) {
1337 DataRelationCollection relations = row.Table.ParentRelations;
1338 int relationCount = relations.Count;
1339 for (int relatedIndex = 0; relatedIndex < relationCount; ++relatedIndex) {
1340 DataRow[] relatedRows = row.GetParentRows(relations[relatedIndex], DataRowVersion.Current);
1342 foreach (DataRow relatedRow in relatedRows) {
1343 int relatedTableIndex = this.Tables.IndexOf(relatedRow.Table);
1344 int relatedRowIndex = relatedRow.Table.Rows.IndexOf(relatedRow);
1346 if (!bitMatrix[relatedTableIndex][relatedRowIndex]) {
1347 bitMatrix[relatedTableIndex][relatedRowIndex] = true;
1349 if (DataRowState.Deleted != relatedRow.RowState) {
1350 // recurse into related rows
1351 MarkRelatedRowsAsModified(bitMatrix, relatedRow);
1358 IList System.ComponentModel.IListSource.GetList() {
1359 return DefaultViewManager;
1362 internal string GetRemotingDiffGram(DataTable table)
1364 StringWriter strWriter = new StringWriter(CultureInfo.InvariantCulture);
1365 XmlTextWriter writer = new XmlTextWriter(strWriter);
1366 writer.Formatting = Formatting.Indented;
1367 if (strWriter != null) {
1368 // Create and save the updates
1369 new NewDiffgramGen(table, false).Save(writer, table);
1372 return strWriter.ToString();
1375 public string GetXml()
1378 Bid.ScopeEnter(out hscp, "<ds.DataSet.GetXml|API> %d#\n", ObjectID);
1381 // StringBuilder strBuilder = new StringBuilder(EstimatedXmlStringSize());
1382 // StringWriter strWriter = new StringWriter(strBuilder);
1383 StringWriter strWriter = new StringWriter(CultureInfo.InvariantCulture);
1384 if (strWriter != null) {
1385 XmlTextWriter w = new XmlTextWriter(strWriter);
1386 w.Formatting = Formatting.Indented;
1387 new XmlDataTreeWriter(this).Save(w, false);
1389 return strWriter.ToString();
1392 Bid.ScopeLeave(ref hscp);
1396 public string GetXmlSchema()
1399 Bid.ScopeEnter(out hscp, "<ds.DataSet.GetXmlSchema|API> %d#\n", ObjectID);
1401 StringWriter strWriter = new StringWriter(CultureInfo.InvariantCulture);
1402 XmlTextWriter writer = new XmlTextWriter(strWriter);
1403 writer.Formatting = Formatting.Indented;
1404 if (strWriter != null) {
1405 (new XmlTreeGen(SchemaFormat.Public)).Save(this, writer);
1408 return strWriter.ToString();
1411 Bid.ScopeLeave(ref hscp);
1415 internal string GetXmlSchemaForRemoting(DataTable table)
1417 StringWriter strWriter = new StringWriter(CultureInfo.InvariantCulture);
1418 XmlTextWriter writer = new XmlTextWriter(strWriter);
1419 writer.Formatting = Formatting.Indented;
1420 if (strWriter != null) {
1421 if (table == null) {
1422 if (this.SchemaSerializationMode == SchemaSerializationMode.ExcludeSchema)
1423 (new XmlTreeGen(SchemaFormat.RemotingSkipSchema)).Save(this, writer);
1425 (new XmlTreeGen(SchemaFormat.Remoting)).Save(this, writer);
1427 else { // no skip schema support for typed datatable
1428 (new XmlTreeGen(SchemaFormat.Remoting)).Save(table, writer);
1432 return strWriter.ToString();
1437 /// <para>Gets a value indicating whether the <see cref='System.Data.DataSet'/> has changes, including new,
1438 /// deleted, or modified rows.</para>
1440 public bool HasChanges()
1442 return HasChanges(DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);
1446 /// <para>Gets a value indicating whether the <see cref='System.Data.DataSet'/> has changes, including new,
1447 /// deleted, or modified rows, filtered by <see cref='System.Data.DataRowState'/>.</para>
1449 public bool HasChanges(DataRowState rowStates)
1452 Bid.ScopeEnter(out hscp, "<ds.DataSet.HasChanges|API> %d#, rowStates=%d{ds.DataRowState}\n", ObjectID, (int)rowStates);
1455 const DataRowState allRowStates = DataRowState.Detached | DataRowState.Unchanged | DataRowState.Added | DataRowState.Deleted | DataRowState.Modified;
1457 if ((rowStates & (~allRowStates)) != 0) {
1458 throw ExceptionBuilder.ArgumentOutOfRange("rowState");
1461 for (int i = 0; i < Tables.Count; i++) {
1462 DataTable table = Tables[i];
1464 for (int j = 0; j < table.Rows.Count; j++) {
1465 DataRow row = table.Rows[j];
1466 if ((row.RowState & rowStates) != 0) {
1474 Bid.ScopeLeave(ref hscp);
1479 /// <para>Infer the XML schema from the specified <see cref='System.IO.TextReader'/> into the <see cref='System.Data.DataSet'/>.</para>
1481 public void InferXmlSchema(XmlReader reader, string[] nsArray)
1484 Bid.ScopeEnter(out hscp, "<ds.DataSet.InferXmlSchema|API> %d#\n", ObjectID);
1489 XmlDocument xdoc = new XmlDocument();
1490 if (reader.NodeType == XmlNodeType.Element) {
1491 XmlNode node = xdoc.ReadNode(reader);
1492 xdoc.AppendChild(node);
1496 if (xdoc.DocumentElement == null)
1499 InferSchema(xdoc, nsArray, XmlReadMode.InferSchema);
1502 Bid.ScopeLeave(ref hscp);
1507 /// <para>Infer the XML schema from the specified <see cref='System.IO.TextReader'/> into the <see cref='System.Data.DataSet'/>.</para>
1509 public void InferXmlSchema(Stream stream, string[] nsArray)
1514 InferXmlSchema(new XmlTextReader(stream), nsArray);
1518 /// <para>Infer the XML schema from the specified <see cref='System.IO.TextReader'/> into the <see cref='System.Data.DataSet'/>.</para>
1520 public void InferXmlSchema(TextReader reader, string[] nsArray)
1525 InferXmlSchema(new XmlTextReader(reader), nsArray);
1529 /// <para>Infer the XML schema from the specified file into the <see cref='System.Data.DataSet'/>.</para>
1531 [ResourceExposure(ResourceScope.Machine)]
1532 [ResourceConsumption(ResourceScope.Machine)]
1533 public void InferXmlSchema(String fileName, string[] nsArray)
1535 XmlTextReader xr = new XmlTextReader(fileName);
1537 InferXmlSchema(xr, nsArray);
1545 /// <para>Reads the XML schema from the specified <see cref='T:System.Xml.XMLReader'/> into the <see cref='System.Data.DataSet'/>
1548 public void ReadXmlSchema(XmlReader reader)
1550 ReadXmlSchema(reader, false);
1553 internal void ReadXmlSchema(XmlReader reader, bool denyResolving)
1556 Bid.ScopeEnter(out hscp, "<ds.DataSet.ReadXmlSchema|INFO> %d#, reader, denyResolving=%d{bool}\n", ObjectID, denyResolving);
1558 int iCurrentDepth = -1;
1563 if (reader is XmlTextReader)
1564 ((XmlTextReader)reader).WhitespaceHandling = WhitespaceHandling.None;
1566 XmlDocument xdoc = new XmlDocument(); // we may need this to infer the schema
1568 if (reader.NodeType == XmlNodeType.Element)
1569 iCurrentDepth = reader.Depth;
1571 reader.MoveToContent();
1573 if (reader.NodeType == XmlNodeType.Element) {
1574 // if reader points to the schema load it...
1576 if (reader.LocalName == Keywords.XDR_SCHEMA && reader.NamespaceURI == Keywords.XDRNS) {
1577 // load XDR schema and exit
1578 ReadXDRSchema(reader);
1582 if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI == Keywords.XSDNS) {
1583 // load XSD schema and exit
1584 ReadXSDSchema(reader, denyResolving);
1588 if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI.StartsWith(Keywords.XSD_NS_START, StringComparison.Ordinal))
1589 throw ExceptionBuilder.DataSetUnsupportedSchema(Keywords.XSDNS);
1591 // ... otherwise backup the top node and all its attributes
1592 XmlElement topNode = xdoc.CreateElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
1593 if (reader.HasAttributes) {
1594 int attrCount = reader.AttributeCount;
1595 for (int i = 0; i < attrCount; i++) {
1596 reader.MoveToAttribute(i);
1597 if (reader.NamespaceURI.Equals(Keywords.XSD_XMLNS_NS))
1598 topNode.SetAttribute(reader.Name, reader.GetAttribute(i));
1600 XmlAttribute attr = topNode.SetAttributeNode(reader.LocalName, reader.NamespaceURI);
1601 attr.Prefix = reader.Prefix;
1602 attr.Value = reader.GetAttribute(i);
1608 while (MoveToElement(reader, iCurrentDepth)) {
1610 // if reader points to the schema load it...
1611 if (reader.LocalName == Keywords.XDR_SCHEMA && reader.NamespaceURI == Keywords.XDRNS) {
1612 // load XDR schema and exit
1613 ReadXDRSchema(reader);
1617 if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI == Keywords.XSDNS) {
1618 // load XSD schema and exit
1619 ReadXSDSchema(reader, denyResolving);
1623 if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI.StartsWith(Keywords.XSD_NS_START, StringComparison.Ordinal))
1624 throw ExceptionBuilder.DataSetUnsupportedSchema(Keywords.XSDNS);
1627 XmlNode node = xdoc.ReadNode(reader);
1628 topNode.AppendChild(node);
1632 // read the closing tag of the current element
1633 ReadEndElement(reader);
1635 // if we are here no schema has been found
1636 xdoc.AppendChild(topNode);
1638 // so we InferSchema
1639 InferSchema(xdoc, null, XmlReadMode.Auto);
1643 Bid.ScopeLeave(ref hscp);
1647 internal bool MoveToElement(XmlReader reader, int depth) {
1648 while (!reader.EOF && reader.NodeType != XmlNodeType.EndElement && reader.NodeType != XmlNodeType.Element && reader.Depth > depth) {
1651 return (reader.NodeType == XmlNodeType.Element);
1654 private static void MoveToElement(XmlReader reader) {
1655 while (!reader.EOF && reader.NodeType != XmlNodeType.EndElement && reader.NodeType != XmlNodeType.Element) {
1659 internal void ReadEndElement(XmlReader reader) {
1660 while (reader.NodeType == XmlNodeType.Whitespace) {
1663 if (reader.NodeType == XmlNodeType.None) {
1666 else if (reader.NodeType == XmlNodeType.EndElement) {
1667 reader.ReadEndElement();
1671 internal void ReadXSDSchema(XmlReader reader, bool denyResolving) {
1672 XmlSchemaSet sSet = new XmlSchemaSet();
1674 int schemaFragmentCount = 1;
1675 //read from current schmema element
1676 if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI == Keywords.XSDNS) {
1677 if (reader.HasAttributes) {
1678 string attribValue = reader.GetAttribute(Keywords.MSD_FRAGMENTCOUNT, Keywords.MSDNS); // this must not move the position
1679 if (!Common.ADP.IsEmpty(attribValue)) {
1680 schemaFragmentCount = int.Parse(attribValue, null);
1685 while (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI == Keywords.XSDNS) {
1686 XmlSchema s = XmlSchema.Read(reader, null);
1689 ReadEndElement(reader);
1691 if (--schemaFragmentCount > 0) {
1692 MoveToElement(reader);
1694 while (reader.NodeType == XmlNodeType.Whitespace) {
1699 XSDSchema schema = new XSDSchema();
1700 schema.LoadSchema(sSet, this);
1703 internal void ReadXDRSchema(XmlReader reader) {
1704 XmlDocument xdoc = new XmlDocument(); // we may need this to infer the schema
1705 XmlNode schNode = xdoc.ReadNode(reader);
1706 xdoc.AppendChild(schNode);
1707 XDRSchema schema = new XDRSchema(this, false);
1708 this.DataSetName = xdoc.DocumentElement.LocalName;
1709 schema.LoadSchema((XmlElement)schNode, this);
1713 /// <para>Reads the XML schema from the specified <see cref='System.IO.Stream'/> into the
1714 /// <see cref='System.Data.DataSet'/>.</para>
1716 public void ReadXmlSchema(Stream stream)
1721 ReadXmlSchema(new XmlTextReader(stream), false);
1725 /// <para>Reads the XML schema from the specified <see cref='System.IO.TextReader'/> into the <see cref='System.Data.DataSet'/>.</para>
1727 public void ReadXmlSchema(TextReader reader)
1732 ReadXmlSchema(new XmlTextReader(reader), false);
1736 /// <para>Reads the XML schema from the specified file into the <see cref='System.Data.DataSet'/>.</para>
1738 [ResourceExposure(ResourceScope.Machine)]
1739 [ResourceConsumption(ResourceScope.Machine)]
1740 public void ReadXmlSchema(String fileName)
1742 XmlTextReader xr = new XmlTextReader(fileName);
1744 ReadXmlSchema(xr, false);
1751 #region WriteXmlSchema
1752 /// <summary>Writes the <see cref='DataSet'/> structure as an XML schema to using the specified <see cref='Stream'/> object.</summary>
1753 /// <param name="stream">A <see cref='Stream'/> object used to write to a file.</param>
1754 public void WriteXmlSchema(Stream stream)
1756 this.WriteXmlSchema(stream, SchemaFormat.Public, (Converter<Type, string>)null);
1759 /// <summary>Writes the <see cref='DataSet'/> structure as an XML schema to using the specified <see cref='Stream'/> object.</summary>
1760 /// <param name="stream">A <see cref='Stream'/> object used to write to a file.</param>
1761 /// <param name="multipleTargetConverter">A delegate used to convert <see cref='Type'/> into string.</param>
1762 public void WriteXmlSchema(Stream stream, Converter<Type, string> multipleTargetConverter)
1764 ADP.CheckArgumentNull(multipleTargetConverter, "multipleTargetConverter");
1765 this.WriteXmlSchema(stream, SchemaFormat.Public, multipleTargetConverter);
1768 /// <summary>Writes the <see cref='DataSet'/> structure as an XML schema to a file.</summary>
1769 /// <param name="fileName">The file name (including the path) to which to write.</param>
1770 [ResourceExposure(ResourceScope.Machine)]
1771 [ResourceConsumption(ResourceScope.Machine)]
1772 public void WriteXmlSchema(String fileName)
1774 this.WriteXmlSchema(fileName, SchemaFormat.Public, (Converter<Type, string>)null);
1777 /// <summary>Writes the <see cref='DataSet'/> structure as an XML schema to a file.</summary>
1778 /// <param name="fileName">The file name (including the path) to which to write.</param>
1779 /// <param name="multipleTargetConverter">A delegate used to convert <see cref='Type'/> into string.</param>
1780 [ResourceExposure(ResourceScope.Machine)]
1781 [ResourceConsumption(ResourceScope.Machine)]
1782 public void WriteXmlSchema(String fileName, Converter<Type, string> multipleTargetConverter)
1784 ADP.CheckArgumentNull(multipleTargetConverter, "multipleTargetConverter");
1785 this.WriteXmlSchema(fileName, SchemaFormat.Public, multipleTargetConverter);
1788 /// <summary>Writes the <see cref='DataSet'/> structure as an XML schema to a <see cref='TextWriter'/> object.</summary>
1789 /// <param name="writer">The <see cref='TextWriter'/> object with which to write.</param>
1790 public void WriteXmlSchema(TextWriter writer)
1792 this.WriteXmlSchema(writer, SchemaFormat.Public, (Converter<Type, string>)null);
1795 /// <summary>Writes the <see cref='DataSet'/> structure as an XML schema to a <see cref='TextWriter'/> object.</summary>
1796 /// <param name="writer">The <see cref='TextWriter'/> object with which to write.</param>
1797 /// <param name="multipleTargetConverter">A delegate used to convert <see cref='Type'/> into string.</param>
1798 public void WriteXmlSchema(TextWriter writer, Converter<Type, string> multipleTargetConverter)
1800 ADP.CheckArgumentNull(multipleTargetConverter, "multipleTargetConverter");
1801 this.WriteXmlSchema(writer, SchemaFormat.Public, multipleTargetConverter);
1804 /// <summary>Writes the <see cref='DataSet'/> structure as an XML schema to an <see cref='XmlWriter'/> object.</summary>
1805 /// <param name="writer">The <see cref='XmlWriter'/> object with which to write.</param>
1806 public void WriteXmlSchema(XmlWriter writer)
1808 this.WriteXmlSchema(writer, SchemaFormat.Public, (Converter<Type, string>)null);
1811 /// <summary>Writes the <see cref='DataSet'/> structure as an XML schema to an <see cref='XmlWriter'/> object.</summary>
1812 /// <param name="writer">The <see cref='XmlWriter'/> object with which to write.</param>
1813 /// <param name="multipleTargetConverter">A delegate used to convert <see cref='Type'/> into string.</param>
1814 public void WriteXmlSchema(XmlWriter writer, Converter<Type, string> multipleTargetConverter)
1816 ADP.CheckArgumentNull(multipleTargetConverter, "multipleTargetConverter");
1817 this.WriteXmlSchema(writer, SchemaFormat.Public, multipleTargetConverter);
1820 [ResourceExposure(ResourceScope.Machine)]
1821 [ResourceConsumption(ResourceScope.Machine)]
1822 private void WriteXmlSchema(String fileName, SchemaFormat schemaFormat, Converter<Type, string> multipleTargetConverter)
1824 XmlTextWriter xw = new XmlTextWriter( fileName, null );
1826 xw.Formatting = Formatting.Indented;
1827 xw.WriteStartDocument(true);
1828 this.WriteXmlSchema(xw, schemaFormat, multipleTargetConverter);
1829 xw.WriteEndDocument();
1836 private void WriteXmlSchema(Stream stream, SchemaFormat schemaFormat, Converter<Type, string> multipleTargetConverter)
1841 XmlTextWriter w = new XmlTextWriter(stream, null);
1842 w.Formatting = Formatting.Indented;
1844 this.WriteXmlSchema(w, schemaFormat, multipleTargetConverter);
1847 private void WriteXmlSchema(TextWriter writer, SchemaFormat schemaFormat, Converter<Type, string> multipleTargetConverter)
1852 XmlTextWriter w = new XmlTextWriter(writer);
1853 w.Formatting = Formatting.Indented;
1855 this.WriteXmlSchema(w, schemaFormat, multipleTargetConverter);
1858 private void WriteXmlSchema(XmlWriter writer, SchemaFormat schemaFormat, Converter<Type, string> multipleTargetConverter)
1861 Bid.ScopeEnter(out hscp, "<ds.DataSet.WriteXmlSchema|INFO> %d#, schemaFormat=%d{ds.SchemaFormat}\n", ObjectID, (int)schemaFormat);
1863 // Generate SchemaTree and write it out
1864 if (writer != null) {
1865 XmlTreeGen treeGen = null;
1866 if (schemaFormat == SchemaFormat.WebService &&
1867 SchemaSerializationMode == SchemaSerializationMode.ExcludeSchema &&
1868 writer.WriteState == WriteState.Element) {
1869 treeGen = new XmlTreeGen(SchemaFormat.WebServiceSkipSchema);
1872 treeGen = new XmlTreeGen(schemaFormat);
1875 treeGen.Save(this, (DataTable)null, writer, false, multipleTargetConverter);
1879 Bid.ScopeLeave(ref hscp);
1886 public XmlReadMode ReadXml(XmlReader reader)
1888 return ReadXml(reader, false);
1892 internal XmlReadMode ReadXml(XmlReader reader, bool denyResolving)
1895 Bid.ScopeEnter(out hscp, "<ds.DataSet.ReadXml|INFO> %d#, denyResolving=%d{bool}\n", ObjectID, denyResolving);
1898 DataTable.DSRowDiffIdUsageSection rowDiffIdUsage = new DataTable.DSRowDiffIdUsageSection();
1900 bool fDataFound = false;
1901 bool fSchemaFound = false;
1902 bool fDiffsFound = false;
1903 bool fIsXdr = false;
1904 int iCurrentDepth = -1;
1905 XmlReadMode ret = XmlReadMode.Auto;
1906 bool isEmptyDataSet = false;
1907 bool topNodeIsProcessed = false; // we chanche topnode and there is just one case that we miss to process it
1908 // it is : <elem attrib1="Attrib">txt</elem>
1910 // clear the hashtable to avoid conflicts between diffgrams, SqlHotFix 782
1911 rowDiffIdUsage.Prepare(this);
1916 if (Tables.Count == 0) {
1917 isEmptyDataSet = true;
1920 if (reader is XmlTextReader)
1921 ((XmlTextReader)reader).WhitespaceHandling = WhitespaceHandling.Significant;
1923 XmlDocument xdoc = new XmlDocument(); // we may need this to infer the schema
1924 XmlDataLoader xmlload = null;
1927 reader.MoveToContent();
1929 if (reader.NodeType == XmlNodeType.Element)
1930 iCurrentDepth = reader.Depth;
1932 if (reader.NodeType == XmlNodeType.Element) {
1933 if ((reader.LocalName == Keywords.DIFFGRAM) && (reader.NamespaceURI == Keywords.DFFNS)) {
1934 this.ReadXmlDiffgram(reader);
1935 // read the closing tag of the current element
1936 ReadEndElement(reader);
1937 return XmlReadMode.DiffGram;
1940 // if reader points to the schema load it
1941 if (reader.LocalName == Keywords.XDR_SCHEMA && reader.NamespaceURI == Keywords.XDRNS) {
1942 // load XDR schema and exit
1943 ReadXDRSchema(reader);
1944 return XmlReadMode.ReadSchema; //since the top level element is a schema return
1947 if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI == Keywords.XSDNS) {
1948 // load XSD schema and exit
1949 ReadXSDSchema(reader, denyResolving);
1950 return XmlReadMode.ReadSchema; //since the top level element is a schema return
1953 if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI.StartsWith(Keywords.XSD_NS_START, StringComparison.Ordinal))
1954 throw ExceptionBuilder.DataSetUnsupportedSchema(Keywords.XSDNS);
1956 // now either the top level node is a table and we load it through dataReader...
1958 // ... or backup the top node and all its attributes because we may need to InferSchema
1959 XmlElement topNode = xdoc.CreateElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
1960 if (reader.HasAttributes) {
1961 int attrCount = reader.AttributeCount;
1962 for (int i = 0; i < attrCount; i++) {
1963 reader.MoveToAttribute(i);
1964 if (reader.NamespaceURI.Equals(Keywords.XSD_XMLNS_NS))
1965 topNode.SetAttribute(reader.Name, reader.GetAttribute(i));
1967 XmlAttribute attr = topNode.SetAttributeNode(reader.LocalName, reader.NamespaceURI);
1968 attr.Prefix = reader.Prefix;
1969 attr.Value = reader.GetAttribute(i);
1974 string rootNodeSimpleContent = reader.Value;
1976 while (MoveToElement(reader, iCurrentDepth)) {
1978 if ((reader.LocalName == Keywords.DIFFGRAM) && (reader.NamespaceURI == Keywords.DFFNS)) {
1979 this.ReadXmlDiffgram(reader);
1980 // read the closing tag of the current element
1981 // YUKON FIX ReadEndElement(reader);
1982 // return XmlReadMode.DiffGram;
1983 ret = XmlReadMode.DiffGram; // continue reading for multiple schemas
1986 // if reader points to the schema load it...
1989 if (!fSchemaFound && !fDataFound && reader.LocalName == Keywords.XDR_SCHEMA && reader.NamespaceURI == Keywords.XDRNS) {
1990 // load XDR schema and exit
1991 ReadXDRSchema(reader);
1992 fSchemaFound = true;
1997 if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI == Keywords.XSDNS) {
1998 // load XSD schema and exit
1999 ReadXSDSchema(reader, denyResolving);
2000 fSchemaFound = true;
2004 if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI.StartsWith(Keywords.XSD_NS_START, StringComparison.Ordinal))
2005 throw ExceptionBuilder.DataSetUnsupportedSchema(Keywords.XSDNS);
2007 if ((reader.LocalName == Keywords.DIFFGRAM) && (reader.NamespaceURI == Keywords.DFFNS)) {
2008 this.ReadXmlDiffgram(reader);
2010 ret = XmlReadMode.DiffGram;
2013 // We have found data IFF the reader.NodeType == Element and reader.depth == currentDepth-1
2014 // if reader.NodeType == whitespace, skip all white spaces.
2015 // skip processing i.e. continue if the first non-whitespace node is not of type element.
2016 while (!reader.EOF && reader.NodeType == XmlNodeType.Whitespace)
2018 if (reader.NodeType != XmlNodeType.Element)
2020 // we found data here
2023 if (!fSchemaFound && Tables.Count == 0) {
2024 XmlNode node = xdoc.ReadNode(reader);
2025 topNode.AppendChild(node);
2028 if (xmlload == null)
2029 xmlload = new XmlDataLoader(this, fIsXdr, topNode, false);
2030 xmlload.LoadData(reader);
2031 topNodeIsProcessed = true; // we process the topnode
2033 ret = XmlReadMode.ReadSchema;
2035 ret = XmlReadMode.IgnoreSchema;
2040 // read the closing tag of the current element
2041 ReadEndElement(reader);
2042 bool isfTopLevelTableSet = false;
2043 bool tmpValue = this.fTopLevelTable;
2044 //While inference we ignore root elements text content
2045 if (!fSchemaFound && Tables.Count == 0 && !topNode.HasChildNodes) { //We shoule not come add SC of root elemnt to topNode if we are not infering
2046 this.fTopLevelTable = true;
2047 isfTopLevelTableSet = true;
2048 if ((rootNodeSimpleContent != null && rootNodeSimpleContent.Length > 0))
2049 topNode.InnerText = rootNodeSimpleContent;
2051 if (!isEmptyDataSet) {
2052 if ((rootNodeSimpleContent != null && rootNodeSimpleContent.Length > 0))
2053 topNode.InnerText = rootNodeSimpleContent;
2056 // now top node contains the data part
2057 xdoc.AppendChild(topNode);
2059 if (xmlload == null)
2060 xmlload = new XmlDataLoader(this, fIsXdr, topNode, false);
2062 if (!isEmptyDataSet && !topNodeIsProcessed) {
2063 XmlElement root = xdoc.DocumentElement;
2064 Debug.Assert(root.NamespaceURI != null, "root.NamespaceURI should not ne null, it should be empty string");
2065 // just recognize that below given Xml represents datatable in toplevel
2066 //<table attr1="foo" attr2="bar" table_Text="junk">text</table>
2067 // only allow root element with simple content, if any
2068 if (root.ChildNodes.Count == 0 ||
2069 ((root.ChildNodes.Count == 1) && root.FirstChild.GetType() == typeof(System.Xml.XmlText))) {
2070 bool initfTopLevelTable = this.fTopLevelTable;
2071 // if root element maps to a datatable
2072 // ds and dt cant have the samm name and ns at the same time, how to write to xml
2073 if (this.DataSetName != root.Name && this.namespaceURI != root.NamespaceURI &&
2074 Tables.Contains(root.Name, (root.NamespaceURI.Length == 0) ? null : root.NamespaceURI, false, true)) {
2075 this.fTopLevelTable = true;
2078 xmlload.LoadData(xdoc);
2081 this.fTopLevelTable = initfTopLevelTable; // this is not for inference, we have schema and we were skipping
2082 // topnode where it was a datatable, We must restore the value
2085 }// above check and below check are orthogonal
2086 // so we InferSchema
2089 if (!fSchemaFound && Tables.Count == 0) {
2090 InferSchema(xdoc, null, XmlReadMode.Auto);
2091 ret = XmlReadMode.InferSchema;
2092 xmlload.FromInference = true;
2094 xmlload.LoadData(xdoc);
2097 xmlload.FromInference = false;
2100 //We dont need this assignement. Once we set it(where we set it during inference), it won't be changed
2101 if (isfTopLevelTableSet)
2102 this.fTopLevelTable = tmpValue;
2109 rowDiffIdUsage.Cleanup();
2113 Bid.ScopeLeave(ref hscp);
2120 public XmlReadMode ReadXml(Stream stream)
2123 return XmlReadMode.Auto;
2125 XmlTextReader xr = new XmlTextReader(stream);
2127 // Prevent Dtd entity in dataset
2128 xr.XmlResolver = null;
2130 return ReadXml(xr, false);
2135 public XmlReadMode ReadXml(TextReader reader)
2138 return XmlReadMode.Auto;
2140 XmlTextReader xr = new XmlTextReader(reader);
2142 // Prevent Dtd entity in dataset
2143 xr.XmlResolver = null;
2145 return ReadXml(xr, false);
2150 [ResourceExposure(ResourceScope.Machine)]
2151 [ResourceConsumption(ResourceScope.Machine)]
2152 public XmlReadMode ReadXml(string fileName)
2154 XmlTextReader xr = new XmlTextReader(fileName);
2156 // Prevent Dtd entity in dataset
2157 xr.XmlResolver = null;
2161 return ReadXml(xr, false);
2168 internal void InferSchema(XmlDocument xdoc, string[] excludedNamespaces, XmlReadMode mode) {
2170 Bid.ScopeEnter(out hscp, "<ds.DataSet.InferSchema|INFO> %d#, mode=%d{ds.XmlReadMode}\n", ObjectID, (int)mode);
2172 string ns = xdoc.DocumentElement.NamespaceURI;
2173 if (null == excludedNamespaces) {
2174 excludedNamespaces = new string[0];
2176 XmlNodeReader xnr = new XmlIgnoreNamespaceReader(xdoc, excludedNamespaces);
2177 System.Xml.Schema.XmlSchemaInference infer = new System.Xml.Schema.XmlSchemaInference();
2179 infer.Occurrence = XmlSchemaInference.InferenceOption.Relaxed;
2181 if (mode == XmlReadMode.InferTypedSchema)
2182 infer.TypeInference = XmlSchemaInference.InferenceOption.Restricted;
2184 infer.TypeInference = XmlSchemaInference.InferenceOption.Relaxed;
2186 XmlSchemaSet schemaSet = infer.InferSchema(xnr);
2187 schemaSet.Compile();
2189 XSDSchema schema = new XSDSchema();
2190 schema.FromInference = true;
2193 schema.LoadSchema(schemaSet, this);
2196 schema.FromInference = false; // this is always false if you are not calling fron inference
2200 Bid.ScopeLeave(ref hscp);
2204 private bool IsEmpty() {
2205 foreach (DataTable table in this.Tables)
2206 if (table.Rows.Count > 0)
2211 private void ReadXmlDiffgram(XmlReader reader) {
2213 Bid.ScopeEnter(out hscp, "<ds.DataSet.ReadXmlDiffgram|INFO> %d#\n", ObjectID);
2215 int d = reader.Depth;
2216 bool fEnforce = this.EnforceConstraints;
2217 this.EnforceConstraints = false;
2219 bool isEmpty = this.IsEmpty();
2225 newDs = this.Clone();
2226 newDs.EnforceConstraints = false;
2229 foreach (DataTable t in newDs.Tables) {
2230 t.Rows.nullInList = 0;
2232 reader.MoveToContent();
2233 if ((reader.LocalName != Keywords.DIFFGRAM) && (reader.NamespaceURI != Keywords.DFFNS))
2236 if (reader.NodeType == XmlNodeType.Whitespace)
2237 MoveToElement(reader, reader.Depth - 1 /*iCurrentDepth*/); // skip over whitespaces.
2239 newDs.fInLoadDiffgram = true;
2241 if (reader.Depth > d) {
2242 if ((reader.NamespaceURI != Keywords.DFFNS) && (reader.NamespaceURI != Keywords.MSDNS)) {
2243 //we should be inside the dataset part
2244 XmlDocument xdoc = new XmlDocument();
2245 XmlElement node = xdoc.CreateElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
2247 if (reader.NodeType == XmlNodeType.Whitespace) {
2248 MoveToElement(reader, reader.Depth - 1 /*iCurrentDepth*/); // skip over whitespaces.
2250 if (reader.Depth - 1 > d) {
2251 XmlDataLoader xmlload = new XmlDataLoader(newDs, false, node, false);
2252 xmlload.isDiffgram = true; // turn on the special processing
2253 xmlload.LoadData(reader);
2255 ReadEndElement(reader);
2256 if (reader.NodeType == XmlNodeType.Whitespace) {
2257 MoveToElement(reader, reader.Depth - 1 /*iCurrentDepth*/); // skip over whitespaces.
2260 Debug.Assert(reader.NodeType != XmlNodeType.Whitespace, "Should not be on Whitespace node");
2262 if (((reader.LocalName == Keywords.SQL_BEFORE) && (reader.NamespaceURI == Keywords.DFFNS)) ||
2263 ((reader.LocalName == Keywords.MSD_ERRORS) && (reader.NamespaceURI == Keywords.DFFNS)))
2266 //this will consume the changes and the errors part
2267 XMLDiffLoader diffLoader = new XMLDiffLoader();
2268 diffLoader.LoadDiffGram(newDs, reader);
2271 // get to the closing diff tag
2272 while (reader.Depth > d) {
2275 // read the closing tag
2276 ReadEndElement(reader);
2279 foreach (DataTable t in newDs.Tables) {
2280 if (t.Rows.nullInList > 0)
2281 throw ExceptionBuilder.RowInsertMissing(t.TableName);
2284 newDs.fInLoadDiffgram = false;
2286 //terrible performance!
2287 foreach (DataTable t in newDs.Tables) {
2288 DataRelation[] nestedParentRelations = t.NestedParentRelations;
2289 foreach (DataRelation rel in nestedParentRelations) {
2290 if (rel.ParentTable == t) {
2291 foreach (DataRow r in t.Rows) {
2292 foreach (DataRelation rel2 in nestedParentRelations) {
2293 r.CheckForLoops(rel2);
2302 if (this.dataSetName == "NewDataSet")
2303 this.dataSetName = newDs.dataSetName;
2304 newDs.EnforceConstraints = fEnforce;
2306 this.EnforceConstraints = fEnforce;
2309 Bid.ScopeLeave(ref hscp);
2316 public XmlReadMode ReadXml(XmlReader reader, XmlReadMode mode)
2318 return ReadXml(reader, mode, false);
2321 internal XmlReadMode ReadXml(XmlReader reader, XmlReadMode mode, bool denyResolving)
2324 Bid.ScopeEnter(out hscp, "<ds.DataSet.ReadXml|INFO> %d#, mode=%d{ds.XmlReadMode}, denyResolving=%d{bool}\n", ObjectID, (int)mode, denyResolving);
2327 XmlReadMode ret = mode;
2332 if (mode == XmlReadMode.Auto) {
2333 // Dev11 915079: nested ReadXml calls on the same DataSet must be done outside of RowDiffIdUsage scope
2334 return ReadXml(reader);
2337 DataTable.DSRowDiffIdUsageSection rowDiffIdUsage = new DataTable.DSRowDiffIdUsageSection();
2340 bool fSchemaFound = false;
2341 bool fDataFound = false;
2342 bool fIsXdr = false;
2343 int iCurrentDepth = -1;
2345 // Dev11 904428: prepare and cleanup rowDiffId hashtable
2346 rowDiffIdUsage.Prepare(this);
2348 if (reader is XmlTextReader)
2349 ((XmlTextReader)reader).WhitespaceHandling = WhitespaceHandling.Significant;
2351 XmlDocument xdoc = new XmlDocument(); // we may need this to infer the schema
2353 if ((mode != XmlReadMode.Fragment) && (reader.NodeType == XmlNodeType.Element))
2354 iCurrentDepth = reader.Depth;
2356 reader.MoveToContent();
2357 XmlDataLoader xmlload = null;
2359 if (reader.NodeType == XmlNodeType.Element) {
2360 XmlElement topNode = null;
2361 if (mode == XmlReadMode.Fragment) {
2362 xdoc.AppendChild(xdoc.CreateElement("ds_sqlXmlWraPPeR"));
2363 topNode = xdoc.DocumentElement;
2365 else { //handle the top node
2366 if ((reader.LocalName == Keywords.DIFFGRAM) && (reader.NamespaceURI == Keywords.DFFNS)) {
2367 if ((mode == XmlReadMode.DiffGram) || (mode == XmlReadMode.IgnoreSchema)) {
2368 this.ReadXmlDiffgram(reader);
2369 // read the closing tag of the current element
2370 ReadEndElement(reader);
2378 if (reader.LocalName == Keywords.XDR_SCHEMA && reader.NamespaceURI == Keywords.XDRNS) {
2379 // load XDR schema and exit
2380 if ((mode != XmlReadMode.IgnoreSchema) && (mode != XmlReadMode.InferSchema) &&
2381 (mode != XmlReadMode.InferTypedSchema))
2383 ReadXDRSchema(reader);
2388 return ret; //since the top level element is a schema return
2391 if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI == Keywords.XSDNS) {
2392 // load XSD schema and exit
2393 if ((mode != XmlReadMode.IgnoreSchema) && (mode != XmlReadMode.InferSchema) &&
2394 (mode != XmlReadMode.InferTypedSchema))
2396 ReadXSDSchema(reader, denyResolving);
2400 return ret; //since the top level element is a schema return
2403 if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI.StartsWith(Keywords.XSD_NS_START, StringComparison.Ordinal))
2404 throw ExceptionBuilder.DataSetUnsupportedSchema(Keywords.XSDNS);
2406 // now either the top level node is a table and we load it through dataReader...
2407 // ... or backup the top node and all its attributes
2408 topNode = xdoc.CreateElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
2409 if (reader.HasAttributes) {
2410 int attrCount = reader.AttributeCount;
2411 for (int i = 0; i < attrCount; i++) {
2412 reader.MoveToAttribute(i);
2413 if (reader.NamespaceURI.Equals(Keywords.XSD_XMLNS_NS))
2414 topNode.SetAttribute(reader.Name, reader.GetAttribute(i));
2416 XmlAttribute attr = topNode.SetAttributeNode(reader.LocalName, reader.NamespaceURI);
2417 attr.Prefix = reader.Prefix;
2418 attr.Value = reader.GetAttribute(i);
2425 while (MoveToElement(reader, iCurrentDepth)) {
2427 if (reader.LocalName == Keywords.XDR_SCHEMA && reader.NamespaceURI == Keywords.XDRNS) {
2429 if (!fSchemaFound && !fDataFound && (mode != XmlReadMode.IgnoreSchema) && (mode != XmlReadMode.InferSchema) &&
2430 (mode != XmlReadMode.InferTypedSchema))
2432 ReadXDRSchema(reader);
2433 fSchemaFound = true;
2442 if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI == Keywords.XSDNS) {
2443 // load XSD schema and exit
2444 if ((mode != XmlReadMode.IgnoreSchema) && (mode != XmlReadMode.InferSchema) &&
2445 (mode != XmlReadMode.InferTypedSchema))
2447 ReadXSDSchema(reader, denyResolving);
2448 fSchemaFound = true;
2456 if ((reader.LocalName == Keywords.DIFFGRAM) && (reader.NamespaceURI == Keywords.DFFNS)) {
2457 if ((mode == XmlReadMode.DiffGram) || (mode == XmlReadMode.IgnoreSchema)) {
2458 this.ReadXmlDiffgram(reader);
2459 ret = XmlReadMode.DiffGram;
2467 if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI.StartsWith(Keywords.XSD_NS_START, StringComparison.Ordinal))
2468 throw ExceptionBuilder.DataSetUnsupportedSchema(Keywords.XSDNS);
2470 if (mode == XmlReadMode.DiffGram) {
2472 continue; // we do not read data in diffgram mode
2475 // if we are here we found some data
2478 if (mode == XmlReadMode.InferSchema || mode == XmlReadMode.InferTypedSchema) { //save the node in DOM until the end;
2479 XmlNode node = xdoc.ReadNode(reader);
2480 topNode.AppendChild(node);
2483 if (xmlload == null)
2484 xmlload = new XmlDataLoader(this, fIsXdr, topNode, mode == XmlReadMode.IgnoreSchema);
2485 xmlload.LoadData(reader);
2487 } //end of the while
2489 // read the closing tag of the current element
2490 ReadEndElement(reader);
2492 // now top node contains the data part
2493 xdoc.AppendChild(topNode);
2494 if (xmlload == null)
2495 xmlload = new XmlDataLoader(this, fIsXdr, mode == XmlReadMode.IgnoreSchema);
2497 if (mode == XmlReadMode.DiffGram) {
2498 // we already got the diffs through XmlReader interface
2503 if (mode == XmlReadMode.InferSchema || mode == XmlReadMode.InferTypedSchema) {
2504 InferSchema(xdoc, null, mode);
2505 ret = XmlReadMode.InferSchema;
2506 xmlload.FromInference = true;
2509 xmlload.LoadData(xdoc);
2512 xmlload.FromInference = false;
2520 // Dev11 904428: prepare and cleanup rowDiffId hashtable
2521 rowDiffIdUsage.Cleanup();
2525 Bid.ScopeLeave(ref hscp);
2532 public XmlReadMode ReadXml(Stream stream, XmlReadMode mode)
2535 return XmlReadMode.Auto;
2537 XmlTextReader reader = (mode == XmlReadMode.Fragment) ? new XmlTextReader(stream, XmlNodeType.Element, null) : new XmlTextReader(stream);
2538 // Prevent Dtd entity in dataset
2539 reader.XmlResolver = null;
2540 return ReadXml(reader, mode, false);
2545 public XmlReadMode ReadXml(TextReader reader, XmlReadMode mode)
2548 return XmlReadMode.Auto;
2550 XmlTextReader xmlreader = (mode == XmlReadMode.Fragment) ? new XmlTextReader(reader.ReadToEnd(), XmlNodeType.Element, null) : new XmlTextReader(reader);
2551 // Prevent Dtd entity in dataset
2552 xmlreader.XmlResolver = null;
2553 return ReadXml(xmlreader, mode, false);
2558 [ResourceExposure(ResourceScope.Machine)]
2559 [ResourceConsumption(ResourceScope.Machine)]
2560 public XmlReadMode ReadXml(string fileName, XmlReadMode mode)
2562 XmlTextReader xr = null;
2563 if (mode == XmlReadMode.Fragment) {
2564 FileStream stream = new FileStream(fileName, FileMode.Open);
2565 xr = new XmlTextReader(stream, XmlNodeType.Element, null);
2568 xr = new XmlTextReader(fileName);
2570 // Prevent Dtd entity in dataset
2571 xr.XmlResolver = null;
2575 return ReadXml(xr, mode, false);
2584 /// Writes schema and data for the DataSet.
2586 public void WriteXml(Stream stream)
2588 WriteXml(stream, XmlWriteMode.IgnoreSchema);
2593 public void WriteXml(TextWriter writer)
2595 WriteXml(writer, XmlWriteMode.IgnoreSchema);
2600 public void WriteXml(XmlWriter writer)
2602 WriteXml(writer, XmlWriteMode.IgnoreSchema);
2606 /// <para>[To be supplied.]</para>
2608 [ResourceExposure(ResourceScope.Machine)]
2609 [ResourceConsumption(ResourceScope.Machine)]
2610 public void WriteXml(String fileName)
2612 WriteXml(fileName, XmlWriteMode.IgnoreSchema);
2616 /// Writes schema and data for the DataSet.
2618 public void WriteXml(Stream stream, XmlWriteMode mode)
2620 if (stream != null) {
2621 XmlTextWriter w = new XmlTextWriter(stream, null);
2622 w.Formatting = Formatting.Indented;
2630 public void WriteXml(TextWriter writer, XmlWriteMode mode)
2632 if (writer != null) {
2633 XmlTextWriter w = new XmlTextWriter(writer);
2634 w.Formatting = Formatting.Indented;
2642 public void WriteXml(XmlWriter writer, XmlWriteMode mode)
2645 Bid.ScopeEnter(out hscp, "<ds.DataSet.WriteXml|API> %d#, mode=%d{ds.XmlWriteMode}\n", ObjectID, (int)mode);
2647 // Generate SchemaTree and write it out
2648 if (writer != null) {
2650 if (mode == XmlWriteMode.DiffGram) {
2651 // Create and save the updates
2652 // new UpdateTreeGen(UpdateTreeGen.UPDATE, (DataRowState)(-1), this).Save(writer, null);
2653 new NewDiffgramGen(this).Save(writer);
2656 // Create and save xml data
2657 new XmlDataTreeWriter(this).Save(writer, mode == XmlWriteMode.WriteSchema);
2662 Bid.ScopeLeave(ref hscp);
2667 /// <para>[To be supplied.]</para>
2669 [ResourceExposure(ResourceScope.Machine)]
2670 [ResourceConsumption(ResourceScope.Machine)]
2671 public void WriteXml(String fileName, XmlWriteMode mode)
2674 Bid.ScopeEnter(out hscp, "<ds.DataSet.WriteXml|API> %d#, fileName='%ls', mode=%d{ds.XmlWriteMode}\n", ObjectID, fileName, (int)mode);
2675 XmlTextWriter xw = new XmlTextWriter(fileName, null);
2677 xw.Formatting = Formatting.Indented;
2678 xw.WriteStartDocument(true);
2680 // Create and save the updates
2681 if (mode == XmlWriteMode.DiffGram) {
2682 new NewDiffgramGen(this).Save(xw);
2685 // Create and save xml data
2686 new XmlDataTreeWriter(this).Save(xw, mode == XmlWriteMode.WriteSchema);
2689 xw.WriteEndDocument();
2693 Bid.ScopeLeave(ref hscp);
2699 /// Gets the collection of parent relations which belong to a
2700 /// specified table.
2703 internal DataRelationCollection GetParentRelations(DataTable table)
2705 return table.ParentRelations;
2710 /// Merges this <see cref='System.Data.DataSet'/> into a specified <see cref='System.Data.DataSet'/>.
2713 public void Merge(DataSet dataSet)
2716 Bid.ScopeEnter(out hscp, "<ds.DataSet.Merge|API> %d#, dataSet=%d\n", ObjectID, (dataSet != null) ? dataSet.ObjectID : 0);
2718 Merge(dataSet, false, MissingSchemaAction.Add);
2721 Bid.ScopeLeave(ref hscp);
2727 /// Merges this <see cref='System.Data.DataSet'/> into a specified <see cref='System.Data.DataSet'/> preserving changes according to
2728 /// the specified argument.
2731 public void Merge(DataSet dataSet, bool preserveChanges)
2734 Bid.ScopeEnter(out hscp, "<ds.DataSet.Merge|API> %d#, dataSet=%d, preserveChanges=%d{bool}\n", ObjectID, (dataSet != null) ? dataSet.ObjectID : 0, preserveChanges);
2736 Merge(dataSet, preserveChanges, MissingSchemaAction.Add);
2739 Bid.ScopeLeave(ref hscp);
2745 /// Merges this <see cref='System.Data.DataSet'/> into a specified <see cref='System.Data.DataSet'/> preserving changes according to
2746 /// the specified argument, and handling an incompatible schema according to the
2747 /// specified argument.
2750 public void Merge(DataSet dataSet, bool preserveChanges, MissingSchemaAction missingSchemaAction) {
2752 Bid.ScopeEnter(out hscp, "<ds.DataSet.Merge|API> %d#, dataSet=%d, preserveChanges=%d{bool}, missingSchemaAction=%d{ds.MissingSchemaAction}\n", ObjectID, (dataSet != null) ? dataSet.ObjectID : 0, preserveChanges, (int)missingSchemaAction);
2756 if (dataSet == null)
2757 throw ExceptionBuilder.ArgumentNull("dataSet");
2759 switch (missingSchemaAction) { // @perfnote: Enum.IsDefined
2760 case MissingSchemaAction.Add:
2761 case MissingSchemaAction.Ignore:
2762 case MissingSchemaAction.Error:
2763 case MissingSchemaAction.AddWithKey:
2764 Merger merger = new Merger(this, preserveChanges, missingSchemaAction);
2765 merger.MergeDataSet(dataSet);
2768 throw Common.ADP.InvalidMissingSchemaAction(missingSchemaAction);
2772 Bid.ScopeLeave(ref hscp);
2778 /// Merges this <see cref='System.Data.DataTable'/> into a specified <see cref='System.Data.DataTable'/>.
2781 public void Merge(DataTable table)
2784 Bid.ScopeEnter(out hscp, "<ds.DataSet.Merge|API> %d#, table=%d\n", ObjectID, (table != null) ? table.ObjectID : 0);
2786 Merge(table, false, MissingSchemaAction.Add);
2789 Bid.ScopeLeave(ref hscp);
2795 /// Merges this <see cref='System.Data.DataTable'/> into a specified <see cref='System.Data.DataTable'/>. with a value to preserve changes
2796 /// made to the target, and a value to deal with missing schemas.
2799 public void Merge(DataTable table, bool preserveChanges, MissingSchemaAction missingSchemaAction)
2802 Bid.ScopeEnter(out hscp, "<ds.DataSet.Merge|API> %d#, table=%d, preserveChanges=%d{bool}, missingSchemaAction=%d{ds.MissingSchemaAction}\n", ObjectID, (table != null) ? table.ObjectID : 0, preserveChanges, (int)missingSchemaAction);
2806 throw ExceptionBuilder.ArgumentNull("table");
2808 switch (missingSchemaAction) { // @perfnote: Enum.IsDefined
2809 case MissingSchemaAction.Add:
2810 case MissingSchemaAction.Ignore:
2811 case MissingSchemaAction.Error:
2812 case MissingSchemaAction.AddWithKey:
2813 Merger merger = new Merger(this, preserveChanges, missingSchemaAction);
2814 merger.MergeTable(table);
2817 throw Common.ADP.InvalidMissingSchemaAction(missingSchemaAction);
2821 Bid.ScopeLeave(ref hscp);
2827 /// <para>[To be supplied.]</para>
2829 public void Merge(DataRow[] rows)
2832 Bid.ScopeEnter(out hscp, "<ds.DataSet.Merge|API> %d#, rows\n", ObjectID);
2834 Merge(rows, false, MissingSchemaAction.Add);
2837 Bid.ScopeLeave(ref hscp);
2842 /// <para>[To be supplied.]</para>
2844 public void Merge(DataRow[] rows, bool preserveChanges, MissingSchemaAction missingSchemaAction)
2847 Bid.ScopeEnter(out hscp, "<ds.DataSet.Merge|API> %d#, preserveChanges=%d{bool}, missingSchemaAction=%d{ds.MissingSchemaAction}\n", ObjectID, preserveChanges, (int)missingSchemaAction);
2851 throw ExceptionBuilder.ArgumentNull("rows");
2853 switch (missingSchemaAction) { // @perfnote: Enum.IsDefined
2854 case MissingSchemaAction.Add:
2855 case MissingSchemaAction.Ignore:
2856 case MissingSchemaAction.Error:
2857 case MissingSchemaAction.AddWithKey:
2858 Merger merger = new Merger(this, preserveChanges, missingSchemaAction);
2859 merger.MergeRows(rows);
2862 throw Common.ADP.InvalidMissingSchemaAction(missingSchemaAction);
2866 Bid.ScopeLeave(ref hscp);
2870 protected virtual void OnPropertyChanging(PropertyChangedEventArgs pcevent)
2872 if (onPropertyChangingDelegate != null)
2873 onPropertyChangingDelegate(this, pcevent);
2877 /// Inheriting classes should override this method to handle this event.
2878 /// Call base.OnMergeFailed to send this event to any registered event
2881 internal void OnMergeFailed(MergeFailedEventArgs mfevent)
2883 if (onMergeFailed != null)
2884 onMergeFailed(this, mfevent);
2886 throw ExceptionBuilder.MergeFailed(mfevent.Conflict);
2889 internal void RaiseMergeFailed(DataTable table, string conflict, MissingSchemaAction missingSchemaAction)
2891 if (MissingSchemaAction.Error == missingSchemaAction)
2892 throw ExceptionBuilder.MergeFailed(conflict);
2894 MergeFailedEventArgs mfevent = new MergeFailedEventArgs(table, conflict);
2895 OnMergeFailed(mfevent);
2899 internal void OnDataRowCreated(DataRow row) {
2900 if (onDataRowCreated != null)
2901 onDataRowCreated(this, row);
2904 internal void OnClearFunctionCalled(DataTable table) {
2905 if (onClearFunctionCalled != null)
2906 onClearFunctionCalled(this, table);
2909 private void OnInitialized() {
2910 if (onInitialized != null) {
2911 onInitialized(this, EventArgs.Empty);
2916 /// This method should be overriden by subclasses to restrict tables being removed.
2918 protected internal virtual void OnRemoveTable(DataTable table) {
2921 internal void OnRemovedTable(DataTable table) {
2922 DataViewManager viewManager = defaultViewManager;
2923 if (null != viewManager) {
2924 viewManager.DataViewSettings.Remove(table);
2929 /// This method should be overriden by subclasses to restrict tables being removed.
2931 protected virtual void OnRemoveRelation(DataRelation relation)
2936 internal void OnRemoveRelationHack(DataRelation relation)
2938 OnRemoveRelation(relation);
2942 protected internal void RaisePropertyChanging(string name)
2944 OnPropertyChanging(new PropertyChangedEventArgs(name));
2947 internal DataTable[] TopLevelTables()
2949 return TopLevelTables(false);
2952 internal DataTable[] TopLevelTables(bool forSchema)
2954 // first let's figure out if we can represent the given dataSet as a tree using
2955 // the fact that all connected undirected graphs with n-1 edges are trees.
2956 List<DataTable> topTables = new List<DataTable>();
2959 // prepend the tables that are nested more than once
2960 for (int i = 0; i < Tables.Count; i++)
2962 DataTable table = Tables[i];
2963 if (table.NestedParentsCount > 1 || table.SelfNested)
2964 topTables.Add(table);
2967 for (int i = 0; i < Tables.Count; i++)
2969 DataTable table = Tables[i];
2970 if (table.NestedParentsCount == 0 && !topTables.Contains(table))
2971 topTables.Add(table);
2973 if (topTables.Count == 0)
2975 return topTables.ToArray();
2979 /// This method rolls back all the changes to have been made to this DataSet since
2980 /// it was loaded or the last time AcceptChanges was called.
2981 /// Any rows still in edit-mode cancel their edits. New rows get removed. Modified and
2982 /// Deleted rows return back to their original state.
2984 public virtual void RejectChanges()
2987 Bid.ScopeEnter(out hscp, "<ds.DataSet.RejectChanges|API> %d#\n", ObjectID);
2989 bool fEnforce = EnforceConstraints;
2990 EnforceConstraints = false;
2991 for (int i = 0; i < Tables.Count; i++)
2992 Tables[i].RejectChanges();
2993 EnforceConstraints = fEnforce;
2996 Bid.ScopeLeave(ref hscp);
3001 /// Resets the dataSet back to it's original state. Subclasses should override
3002 /// to restore back to it's original state.
3005 public virtual void Reset()
3008 Bid.ScopeEnter(out hscp, "<ds.DataSet.Reset|API> %d#\n", ObjectID);
3010 for (int i = 0; i < Tables.Count; i++) {
3011 ConstraintCollection cons = Tables[i].Constraints;
3012 for (int j = 0; j < cons.Count; ) {
3013 if (cons[j] is ForeignKeyConstraint) {
3014 cons.Remove(cons[j]);
3020 // SQLBU 502734: because of SQLBU 501916, dependent tables need to be notified when a table is cleared
3021 // if relations are removed first, then exceptions happen
3027 Bid.ScopeLeave(ref hscp);
3031 internal bool ValidateCaseConstraint() {
3033 Bid.ScopeEnter(out hscp, "<ds.DataSet.ValidateCaseConstraint|INFO> %d#\n", ObjectID);
3035 DataRelation relation = null;
3036 for (int i = 0; i < Relations.Count; i++) {
3037 relation = Relations[i];
3038 if (relation.ChildTable.CaseSensitive != relation.ParentTable.CaseSensitive)
3042 ForeignKeyConstraint constraint = null;
3043 ConstraintCollection constraints = null;
3044 for (int i = 0; i < Tables.Count; i++) {
3045 constraints = Tables[i].Constraints;
3046 for (int j = 0; j < constraints.Count; j++) {
3047 if (constraints[j] is ForeignKeyConstraint) {
3048 constraint = (ForeignKeyConstraint)constraints[j];
3049 if (constraint.Table.CaseSensitive != constraint.RelatedTable.CaseSensitive)
3057 Bid.ScopeLeave(ref hscp);
3061 internal bool ValidateLocaleConstraint() {
3063 Bid.ScopeEnter(out hscp, "<ds.DataSet.ValidateLocaleConstraint|INFO> %d#\n", ObjectID);
3065 DataRelation relation = null;
3066 for (int i = 0; i < Relations.Count; i++) {
3067 relation = Relations[i];
3068 if (relation.ChildTable.Locale.LCID != relation.ParentTable.Locale.LCID)
3072 ForeignKeyConstraint constraint = null;
3073 ConstraintCollection constraints = null;
3074 for (int i = 0; i < Tables.Count; i++) {
3075 constraints = Tables[i].Constraints;
3076 for (int j = 0; j < constraints.Count; j++) {
3077 if (constraints[j] is ForeignKeyConstraint) {
3078 constraint = (ForeignKeyConstraint)constraints[j];
3079 if (constraint.Table.Locale.LCID != constraint.RelatedTable.Locale.LCID)
3087 Bid.ScopeLeave(ref hscp);
3091 // [....]: may be better to rewrite this as nonrecursive?
3092 internal DataTable FindTable(DataTable baseTable, PropertyDescriptor[] props, int propStart) {
3093 if (props.Length < propStart + 1)
3096 PropertyDescriptor currentProp = props[propStart];
3098 if (baseTable == null) {
3099 // the accessor is the table name. if we don't find it, return null.
3100 if (currentProp is DataTablePropertyDescriptor) {
3101 return FindTable(((DataTablePropertyDescriptor)currentProp).Table, props, propStart + 1);
3106 if (currentProp is DataRelationPropertyDescriptor) {
3107 return FindTable(((DataRelationPropertyDescriptor)currentProp).Relation.ChildTable, props, propStart + 1);
3113 protected virtual void ReadXmlSerializable(XmlReader reader) {
3114 //WebData 96421 and 104709, this is DataSet side fix for the thrown exception
3115 // <DataSet xsi:nil="true"> does not mean DataSet is null,but it does not have any child
3116 // so dont do anything, ignore the attributes and just return empty DataSet;
3117 this.UseDataSetSchemaOnly = false;
3118 this.UdtIsWrapped = false;
3120 if (reader.HasAttributes) {
3121 const string xsinill = Keywords.XSI + ":" + Keywords.XSI_NIL;
3122 if (reader.MoveToAttribute(xsinill)) {
3123 string nilAttrib = reader.GetAttribute(xsinill);
3124 if (string.Compare(nilAttrib, "true", StringComparison.Ordinal) == 0) {// case sensitive true comparison
3125 MoveToElement(reader, 1);
3130 const string useDataSetSchemaOnlyString = Keywords.MSD + ":" + Keywords.USEDATASETSCHEMAONLY;
3131 if (reader.MoveToAttribute(useDataSetSchemaOnlyString)) {
3132 string _useDataSetSchemaOnly = reader.GetAttribute(useDataSetSchemaOnlyString);
3133 if (string.Equals(_useDataSetSchemaOnly, "true", StringComparison.Ordinal) ||
3134 string.Equals(_useDataSetSchemaOnly, "1", StringComparison.Ordinal))
3136 this.UseDataSetSchemaOnly = true;
3138 else if (!string.Equals(_useDataSetSchemaOnly, "false", StringComparison.Ordinal) &&
3139 !string.Equals(_useDataSetSchemaOnly, "0", StringComparison.Ordinal))
3141 throw ExceptionBuilder.InvalidAttributeValue(Keywords.USEDATASETSCHEMAONLY, _useDataSetSchemaOnly);
3145 const string udtIsWrappedString = Keywords.MSD + ":" + Keywords.UDTCOLUMNVALUEWRAPPED;
3146 if (reader.MoveToAttribute(udtIsWrappedString)) {
3147 string _udtIsWrappedString = reader.GetAttribute(udtIsWrappedString);
3148 if (string.Equals(_udtIsWrappedString, "true", StringComparison.Ordinal) ||
3149 string.Equals(_udtIsWrappedString, "1", StringComparison.Ordinal))
3151 this.UdtIsWrapped = true;
3154 else if (!string.Equals(_udtIsWrappedString, "false", StringComparison.Ordinal) &&
3155 !string.Equals(_udtIsWrappedString, "0", StringComparison.Ordinal))
3157 throw ExceptionBuilder.InvalidAttributeValue(Keywords.UDTCOLUMNVALUEWRAPPED, _udtIsWrappedString);
3161 ReadXml(reader, XmlReadMode.DiffGram, true);
3164 protected virtual System.Xml.Schema.XmlSchema GetSchemaSerializable() {
3168 /************************************************************************
3170 int_tools\webserviceadmin.exe -install Application Application.dll
3173 http://localhost/application/service.asmx?wsdl
3175 wsdl.exe /namespace:UserNamespace http://localhost/Application/Service.asmx?wsdl /out:Service.cs
3177 The V1.0 & V1.1 WSDL for Untyped DataSet being returned as a result (no parameters)
3178 <s:element name="anyUserSpecifiedMethodName">
3179 <!-- This is where parameters go -->
3182 <s:element name="anyUserSpecifiedMethodName"+"Response">
3185 <s:element minOccurs="0" maxOccurs="1" name="anyUserSpecifiedMethodName"+"Result">
3188 <s:element ref="s:schema" />
3197 The V1.0 & V1.1 WSDL for Untyped DataSet as parameter, string for the result
3198 <s:element name="anyUserSpecifiedMethodName">
3199 <!-- This is where parameters go -->
3202 <s:element minOccurs="0" maxOccurs="1" name="set">
3205 <s:element ref="s:schema" />
3213 <s:element name="anyUserSpecifiedMethodName"+"Response">
3216 <s:element minOccurs="0" maxOccurs="1" name="anyUserSpecifiedMethodName"+"Result" type="s:string" />
3221 The V2.0 WSDL for Untyped DataSet being returned as a result (no parameters)
3222 <s:element name="anyUserSpecifiedMethodName">
3223 <!-- This is where parameters go -->
3226 <s:element name="anyUserSpecifiedMethodName"+"Response">
3229 <s:element minOccurs="0" maxOccurs="1" name="anyUserSpecifiedMethodName"+"Result">
3231 <s:sequence maxOccurs="unbounded">
3232 <s:any minOccurs="0" namespace="http://www.w3.org/2001/XMLSchema" processContents="lax" />
3233 <s:any minOccurs="0" namespace="urn:schemas-microsoft-com:xml-diffgram-v1" processContents="lax" />
3241 The V2.0 WSDL for Untyped DataSet as a parameter, string for the result
3242 <s:element name="anyUserSpecifiedMethodName">
3243 <!-- This is where parameters go -->
3246 <s:element minOccurs="0" maxOccurs="1" name="anyUserSpecifiedParameterName">
3248 <s:sequence maxOccurs="unbounded">
3249 <s:any minOccurs="0" namespace="http://www.w3.org/2001/XMLSchema" processContents="lax" />
3250 <s:any minOccurs="0" namespace="urn:schemas-microsoft-com:xml-diffgram-v1" processContents="lax" />
3257 <s:element name="anyUserSpecifiedMethodName"+"Response">
3260 <s:element minOccurs="0" maxOccurs="1" name="anyUserSpecifiedMethodName"+"Result" type="s:string" />
3265 The V1.0, V1.1 & V2.0 WSDL for Typed DataSet
3266 <s:import schemaLocation="http://localhost/application/service.asmx?schema=typedDataSetName" namespace="typedDataSetName" />
3267 <s:element name="anyUserSpecifiedMethodName">
3268 <!-- This is where parameters go -->
3271 <s:element name="anyUserSpecifiedMethodName"+"Response">
3274 <s:element minOccurs="0" maxOccurs="1" name="anyUserSpecifiedMethodName"+"Result">
3277 <s:any namespace="typedDataSetName" />
3284 ************************************************************************/
3285 public static XmlSchemaComplexType GetDataSetSchema(XmlSchemaSet schemaSet) {
3286 // For performance resons we are exploiting the fact that config files content is constant
3287 // for a given appdomain so we can safely cache the prepared schema complex type and reuse it
3288 if (schemaTypeForWSDL == null) { // to change the config file, appdomain needs to restart; so it seems safe to cache the schema
3289 XmlSchemaComplexType tempWSDL = new XmlSchemaComplexType();
3290 XmlSchemaSequence sequence = new XmlSchemaSequence();
3292 if (PublishLegacyWSDL())
3293 { // Default is Version 1.0
3294 XmlSchemaElement elem = new XmlSchemaElement();
3295 elem.RefName = new XmlQualifiedName(Keywords.XSD_SCHEMA, Keywords.XSDNS);
3296 sequence.Items.Add(elem);
3297 XmlSchemaAny any = new XmlSchemaAny();
3298 sequence.Items.Add(any);
3301 { // this means Version == V2.0 or newer
3302 XmlSchemaAny any = new XmlSchemaAny();
3303 any.Namespace = XmlSchema.Namespace;
3305 any.ProcessContents = XmlSchemaContentProcessing.Lax;
3306 sequence.Items.Add(any);
3308 any = new XmlSchemaAny();
3309 any.Namespace = Keywords.DFFNS;
3310 any.MinOccurs = 0; // when recognizing WSDL - MinOccurs="0" denotes DataSet, a MinOccurs="1" for DataTable
3311 any.ProcessContents = XmlSchemaContentProcessing.Lax;
3312 sequence.Items.Add(any);
3313 sequence.MaxOccurs = Decimal.MaxValue;
3315 tempWSDL.Particle = sequence;
3317 schemaTypeForWSDL = tempWSDL;
3319 return schemaTypeForWSDL;
3322 /********************************************
3325 <section name="system.data.dataset" type="System.Configuration.NameValueFileSectionHandler, System, Version=%ASSEMBLY_VERSION%, Culture=neutral, PublicKeyToken=%ECMA_PUBLICKEY%" restartOnExternalChanges="false" />
3327 <system.data.dataset>
3328 <!-- if WSDL_VERSION is missing it will default to 1.0
3329 <add key="WSDL_VERSION" value="1.0"/>
3331 <add key="WSDL_VERSION" value="2.0"/>
3332 </system.data.dataset>
3334 *******************************************/
3335 private static bool PublishLegacyWSDL()
3337 Single version = 1.0f; // Default is Version 1.0
3338 #if !NO_CONFIGURATION
3339 NameValueCollection settings = (NameValueCollection)PrivilegedConfigurationManager.GetSection(Keywords.WS_DATASETFULLQNAME);
3340 if (settings != null)
3342 string[] values = settings.GetValues(Keywords.WS_VERSION);
3343 if ((null != values) && (0 < values.Length) && (null != values[0]))
3344 { // will throw FormatException if not a valid number
3345 version = Single.Parse(values[0], CultureInfo.InvariantCulture);
3349 return (version < 2.0f); // if config does not exist, Default is Version 1.0
3352 XmlSchema IXmlSerializable.GetSchema() {
3353 if (GetType() == typeof(DataSet)) {
3356 MemoryStream stream = new MemoryStream();
3357 // WriteXmlSchema(new XmlTextWriter(stream, null));
3358 XmlWriter writer = new XmlTextWriter(stream, null);
3359 if (writer != null) {
3360 (new XmlTreeGen(SchemaFormat.WebService)).Save(this, writer);
3362 stream.Position = 0;
3363 return XmlSchema.Read(new XmlTextReader(stream), null);
3364 // return GetSchemaSerializable();
3367 void IXmlSerializable.ReadXml(XmlReader reader) {
3368 bool fNormalization = true;
3369 XmlTextReader xmlTextReader = null;
3370 IXmlTextParser xmlTextParser = reader as IXmlTextParser;
3371 if (xmlTextParser != null) {
3372 fNormalization = xmlTextParser.Normalized;
3373 xmlTextParser.Normalized = false;
3376 xmlTextReader = reader as XmlTextReader;
3377 if (xmlTextReader != null) {
3378 fNormalization = xmlTextReader.Normalization;
3379 xmlTextReader.Normalization = false;
3383 ReadXmlSerializable(reader);
3385 if (xmlTextParser != null)
3386 xmlTextParser.Normalized = fNormalization;
3387 else if (xmlTextReader != null)
3388 xmlTextReader.Normalization = fNormalization;
3391 void IXmlSerializable.WriteXml(XmlWriter writer) {
3392 this.WriteXmlSchema(writer, SchemaFormat.WebService, (Converter<Type, string>)null);
3393 this.WriteXml(writer, XmlWriteMode.DiffGram);
3396 public virtual void Load(IDataReader reader, LoadOption loadOption, FillErrorEventHandler errorHandler, params DataTable[] tables) {
3398 Bid.ScopeEnter(out hscp, "<ds.DataSet.Load|API> reader, loadOption=%d{ds.LoadOption}", (int)loadOption);
3400 foreach (DataTable dt in tables) {
3401 Common.ADP.CheckArgumentNull(dt, "tables");
3402 if (dt.DataSet != this) {
3403 throw ExceptionBuilder.TableNotInTheDataSet(dt.TableName);
3406 Common.LoadAdapter adapter = new Common.LoadAdapter();
3407 adapter.FillLoadOption = loadOption;
3408 adapter.MissingSchemaAction = MissingSchemaAction.AddWithKey;
3409 if (null != errorHandler) {
3410 adapter.FillError += errorHandler;
3412 adapter.FillFromReader(tables, reader, 0, 0);
3414 if (!reader.IsClosed && !reader.NextResult()) { //
3419 Bid.ScopeLeave(ref hscp);
3423 public void Load(IDataReader reader, LoadOption loadOption, params DataTable[] tables) {
3424 Load(reader, loadOption, null, tables);
3427 public void Load(IDataReader reader, LoadOption loadOption, params string[] tables) {
3428 Common.ADP.CheckArgumentNull(tables, "tables");
3429 DataTable[] dataTables = new DataTable[tables.Length];
3430 for (int i = 0; i < tables.Length; i++) {
3431 DataTable tempDT = this.Tables[tables[i]];
3432 if (null == tempDT) {
3433 tempDT = new DataTable(tables[i]);
3434 // fxcop: new DataTable should inherit the CaseSensitive, Locale, Namespace from DataSet
3437 dataTables[i] = tempDT;
3439 Load(reader, loadOption, null, dataTables);
3442 public DataTableReader CreateDataReader() {
3443 if (Tables.Count == 0)
3444 throw ExceptionBuilder.CannotCreateDataReaderOnEmptyDataSet();
3446 DataTable[] dataTables = new DataTable[Tables.Count];
3447 for (int i = 0; i < Tables.Count; i++) {
3448 dataTables[i] = Tables[i];
3450 return CreateDataReader(dataTables);
3453 public DataTableReader CreateDataReader(params DataTable[] dataTables) {
3455 Bid.ScopeEnter(out hscp, "<ds.DataSet.GetDataReader|API> %d#\n", ObjectID);
3457 if (dataTables.Length == 0)
3458 throw ExceptionBuilder.DataTableReaderArgumentIsEmpty();
3460 for (int i = 0; i < dataTables.Length; i++) {
3461 if (dataTables[i] == null)
3462 throw ExceptionBuilder.ArgumentContainsNullValue();
3465 return new DataTableReader(dataTables);
3468 Bid.ScopeLeave(ref hscp);
3472 internal string MainTableName {
3474 return mainTableName;
3477 this.mainTableName = value;
3481 internal int ObjectID {
3490 public class DataSetSchemaImporterExtension : SchemaImporterExtension {
3491 // DataSetSchemaImporterExtension is used for WebServices, it is used to recognize the schema of DataSet within wsdl
3492 // If a non 2.0 enabled DataSetSchemaImporterExtension, wsdl will generate a classes that you can't cast to dataset / datatable
3494 Hashtable importedTypes = new Hashtable();
3497 /// <para>[To be supplied.]</para>
3499 public override string ImportSchemaType(string name, string schemaNamespace, XmlSchemaObject context, XmlSchemas schemas, XmlSchemaImporter importer, CodeCompileUnit compileUnit, CodeNamespace mainNamespace, CodeGenerationOptions options, CodeDomProvider codeProvider) {
3500 IList values = schemas.GetSchemas(schemaNamespace);
3501 if (values.Count != 1) {
3504 XmlSchema schema = values[0] as XmlSchema;
3507 XmlSchemaType type = (XmlSchemaType)schema.SchemaTypes[new XmlQualifiedName(name, schemaNamespace)];
3508 return ImportSchemaType(type, context, schemas, importer, compileUnit, mainNamespace, options, codeProvider);
3512 /// <para>[To be supplied.]</para>
3514 public override string ImportSchemaType(XmlSchemaType type, XmlSchemaObject context, XmlSchemas schemas, XmlSchemaImporter importer, CodeCompileUnit compileUnit, CodeNamespace mainNamespace, CodeGenerationOptions options, CodeDomProvider codeProvider) {
3518 if (importedTypes[type] != null) {
3519 mainNamespace.Imports.Add(new CodeNamespaceImport(typeof(DataSet).Namespace));
3520 compileUnit.ReferencedAssemblies.Add("System.Data.dll");
3521 return (string)importedTypes[type];
3523 if (!(context is XmlSchemaElement))
3526 XmlSchemaElement e = (XmlSchemaElement)context;
3528 // recognizing the following is important, but not as part of SQLPT 120015394: Support WSI Compliant WSDL for DataSet
3529 // <xs:element name="NewDataSet" msdata:IsDataSet="true">
3530 // see also SQLBU 338644, 410965, 423446
3533 // return GenerateTypedDataSet(e, schemas, mainNamespace, compileUnit.ReferencedAssemblies, codeProvider);
3536 if (type is XmlSchemaComplexType) {
3537 XmlSchemaComplexType ct = (XmlSchemaComplexType)type;
3539 if (ct.Particle is XmlSchemaSequence)
3541 XmlSchemaObjectCollection items = ((XmlSchemaSequence)ct.Particle).Items;
3542 if ((2 == items.Count) && (items[0] is XmlSchemaAny) && (items[1] is XmlSchemaAny))
3544 XmlSchemaAny any0 = (XmlSchemaAny)items[0];
3545 XmlSchemaAny any1 = (XmlSchemaAny)items[1];
3546 if ((any0.Namespace == XmlSchema.Namespace) && (any1.Namespace == "urn:schemas-microsoft-com:xml-diffgram-v1"))
3547 { // new diffgramm format
3549 foreach (XmlSchemaAttribute a in ct.Attributes)
3551 if (a.Name == "namespace")
3553 ns = a.FixedValue.Trim();
3557 bool isDataSet = false;
3559 // check for DataSet or DataTable
3560 if (((XmlSchemaSequence)ct.Particle).MaxOccurs == Decimal.MaxValue)
3564 else if (any0.MaxOccurs == Decimal.MaxValue)
3574 { //Un-Typed DataSet / DataTable
3575 string typeName = isDataSet ? typeof(DataSet).FullName : typeof(DataTable).FullName;
3576 importedTypes.Add(type, typeName);
3577 mainNamespace.Imports.Add(new CodeNamespaceImport(typeof(DataSet).Namespace));
3578 compileUnit.ReferencedAssemblies.Add("System.Data.dll");
3582 { // Typed DataSet / DataTable
3583 foreach (XmlSchema schema in schemas.GetSchemas(ns))
3585 if ((schema != null) && (schema.Id != null))
3587 XmlSchemaElement ds = FindDataSetElement(schema); // implement FindDataTableElement(schema)
3590 return ImportSchemaType(ds.SchemaType, ds, schemas, importer, compileUnit, mainNamespace, options, codeProvider);
3600 if (ct.Particle is XmlSchemaSequence || ct.Particle is XmlSchemaAll) {
3601 XmlSchemaObjectCollection items = ((XmlSchemaGroupBase)ct.Particle).Items;
3602 if (items.Count == 2) {
3603 if (!(items[0] is XmlSchemaElement && items[1] is XmlSchemaAny)) return null;
3604 XmlSchemaElement schema = (XmlSchemaElement)items[0];
3605 if (!(schema.RefName.Name == "schema" && schema.RefName.Namespace == XmlSchema.Namespace)) return null;
3606 string typeName = typeof(DataSet).FullName;
3607 importedTypes.Add(type, typeName);
3608 mainNamespace.Imports.Add(new CodeNamespaceImport(typeof(DataSet).Namespace));
3609 compileUnit.ReferencedAssemblies.Add("System.Data.dll");
3612 else if (1 == items.Count)
3614 XmlSchemaAny any = items[0] as XmlSchemaAny;
3615 if ((null != any) &&
3616 (null != any.Namespace) &&
3617 (any.Namespace.IndexOfAny(new char[] { '#', ' ' }) < 0)) // special syntax (##any, ##other, ...) or more than one Uri present
3619 foreach (XmlSchema schema in schemas.GetSchemas(any.Namespace))
3621 if ((null != schema) &&
3622 (null != schema.Id))
3624 XmlSchemaElement ds = FindDataSetElement(schema);
3627 return ImportSchemaType(ds.SchemaType, ds, schemas, importer, compileUnit, mainNamespace, options, codeProvider);
3642 internal XmlSchemaElement FindDataSetElement(XmlSchema schema) {
3643 foreach (XmlSchemaObject item in schema.Items) {
3644 if (item is XmlSchemaElement && IsDataSet((XmlSchemaElement)item)) {
3645 return (XmlSchemaElement)item;
3651 internal string GenerateTypedDataSet(XmlSchemaElement element, XmlSchemas schemas, CodeNamespace codeNamespace, StringCollection references, CodeDomProvider codeProvider) {
3652 if (element == null)
3655 if (importedTypes[element.SchemaType] != null)
3656 return (string)importedTypes[element.SchemaType];
3658 IList values = schemas.GetSchemas(element.QualifiedName.Namespace);
3659 if (values.Count != 1) {
3662 XmlSchema schema = values[0] as XmlSchema;
3666 DataSet ds = new DataSet();
3669 using (MemoryStream stream = new MemoryStream()) {
3670 schema.Write(stream);
3671 stream.Position = 0;
3672 ds.ReadXmlSchema(stream);
3675 #pragma warning disable 618 // ignore obsolete warning about TypedDataSetGenerator
3676 CodeTypeDeclaration dsClass = new TypedDataSetGenerator().GenerateCode(ds, codeNamespace, codeProvider.CreateGenerator());
3677 #pragma warning restore 618
3678 string typeName = dsClass.Name;
3679 importedTypes.Add(element.SchemaType, typeName);
3680 references.Add("System.Data.dll");
3684 internal static bool IsDataSet(XmlSchemaElement e) {
3685 if (e.UnhandledAttributes != null) {
3686 foreach (XmlAttribute a in e.UnhandledAttributes) {
3687 if (a.LocalName == "IsDataSet" && a.NamespaceURI == Keywords.MSDNS) {
3688 // currently the msdata:IsDataSet uses its own format for the boolean values
3689 if (a.Value == "True" || a.Value == "true" || a.Value == "1") return true;