Updates referencesource to .NET 4.7
[mono-project.git] / mcs / class / referencesource / System.Data / System / Data / DataSet.cs
blob4f14761eaf017202c17743d4647b1a3095ffeb9c
1 //------------------------------------------------------------------------------
2 // <copyright file="DataSet.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
4 // </copyright>
5 // <owner current="true" primary="true">Microsoft</owner>
6 // <owner current="true" primary="false">Microsoft</owner>
7 //------------------------------------------------------------------------------
9 namespace System.Data {
10 using System;
11 using System.Text;
12 using System.Runtime.Serialization;
13 using System.ComponentModel;
14 using System.Diagnostics;
15 using System.Globalization;
16 using System.IO;
17 using System.Collections;
18 using System.Collections.Generic;
19 using System.Collections.Specialized;
20 using System.Xml;
21 using System.Xml.Serialization;
22 #if !NO_CONFIGURATION
23 using System.Xml.Serialization.Advanced;
24 #endif
25 using System.Xml.Schema;
26 using System.Runtime.Serialization.Formatters.Binary; //Binary Formatter
27 using System.CodeDom;
28 using System.CodeDom.Compiler;
29 using System.Configuration;
30 using System.Data.Common;
31 using System.Runtime.Versioning;
32 using System.Runtime.CompilerServices;
34 #if !COREFX
35 /// <devdoc>
36 /// <para>
37 /// Represents an in-memory cache of data.
38 /// </para>
39 /// </devdoc>
41 ResDescriptionAttribute(Res.DataSetDescr),
42 DefaultProperty("DataSetName"),
43 ToolboxItem("Microsoft.VSDesigner.Data.VS.DataSetToolboxItem, " + AssemblyRef.MicrosoftVSDesigner),
44 Designer("Microsoft.VSDesigner.Data.VS.DataSetDesigner, " + AssemblyRef.MicrosoftVSDesigner),
45 Serializable,
46 XmlSchemaProvider("GetDataSetSchema"),
47 XmlRoot("DataSet")
49 public class DataSet : MarshalByValueComponent, System.ComponentModel.IListSource, IXmlSerializable, ISupportInitializeNotification, ISerializable {
51 private DataViewManager defaultViewManager;
53 // Public Collections
54 private readonly DataTableCollection tableCollection;
55 private readonly DataRelationCollection relationCollection;
56 internal PropertyCollection extendedProperties = null;
57 private string dataSetName = "NewDataSet";
58 private string _datasetPrefix = String.Empty;
59 internal string namespaceURI = string.Empty;
60 private bool enforceConstraints = true;
61 private const String KEY_XMLSCHEMA = "XmlSchema";
62 private const String KEY_XMLDIFFGRAM = "XmlDiffGram";
64 // globalization stuff
65 private bool _caseSensitive;
66 private CultureInfo _culture;
67 private bool _cultureUserSet;
69 // Internal definitions
70 internal bool fInReadXml = false;
71 internal bool fInLoadDiffgram = false;
72 internal bool fTopLevelTable = false;
73 internal bool fInitInProgress = false;
74 internal bool fEnableCascading = true;
75 internal bool fIsSchemaLoading = false;
76 private bool fBoundToDocument; // for XmlDataDocument
78 // Events
79 private PropertyChangedEventHandler onPropertyChangingDelegate;
80 private MergeFailedEventHandler onMergeFailed;
81 private DataRowCreatedEventHandler onDataRowCreated; // Internal for XmlDataDocument only
82 private DataSetClearEventhandler onClearFunctionCalled; // Internal for XmlDataDocument only
83 private System.EventHandler onInitialized;
86 internal readonly static DataTable[] zeroTables = new DataTable[0];
87 internal string mainTableName = "";
89 //default remoting format is XML
90 private SerializationFormat _remotingFormat = SerializationFormat.Xml;
92 private object _defaultViewManagerLock = new Object();
94 private static int _objectTypeCount; // Bid counter
95 private readonly int _objectID = System.Threading.Interlocked.Increment(ref _objectTypeCount);
96 private static XmlSchemaComplexType schemaTypeForWSDL = null;
98 internal bool UseDataSetSchemaOnly; // UseDataSetSchemaOnly , for YUKON
99 internal bool UdtIsWrapped; // if UDT is wrapped , for YUKON
101 /// <devdoc>
102 /// <para>Initializes a new instance of the <see cref='System.Data.DataSet'/> class.</para>
103 /// </devdoc>
104 public DataSet() {
105 GC.SuppressFinalize(this);
106 Bid.Trace("<ds.DataSet.DataSet|API> %d#\n", ObjectID); // others will call this constr
107 // Set default locale
108 this.tableCollection = new DataTableCollection(this);
109 this.relationCollection = new DataRelationCollection.DataSetRelationCollection(this);
110 _culture = CultureInfo.CurrentCulture; // Set default locale
113 /// <devdoc>
114 /// <para>Initializes a new instance of a <see cref='System.Data.DataSet'/>
115 /// class with the given name.</para>
116 /// </devdoc>
117 public DataSet(string dataSetName)
118 : this()
120 this.DataSetName = dataSetName;
124 DefaultValue(SerializationFormat.Xml)
126 public SerializationFormat RemotingFormat {
127 get {
128 return _remotingFormat;
130 set {
131 if (value != SerializationFormat.Binary && value != SerializationFormat.Xml) {
132 throw ExceptionBuilder.InvalidRemotingFormat(value);
134 _remotingFormat = value;
135 // this property is inherited to DataTable from DataSet.So we set this value to DataTable also
136 for (int i = 0; i < Tables.Count; i++) {
137 Tables[i].RemotingFormat = value;
142 [BrowsableAttribute(false)]
143 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
144 public virtual SchemaSerializationMode SchemaSerializationMode { //Typed DataSet calls into this
145 get {
146 return SchemaSerializationMode.IncludeSchema;
148 set {
149 if (value != SchemaSerializationMode.IncludeSchema) {
150 throw ExceptionBuilder.CannotChangeSchemaSerializationMode();
155 // Check whether the stream is binary serialized.
156 // 'static' function that consumes SerializationInfo
157 protected bool IsBinarySerialized(SerializationInfo info, StreamingContext context) {// mainly for typed DS
158 // our default remoting format is XML
159 SerializationFormat remotingFormat = SerializationFormat.Xml;
160 SerializationInfoEnumerator e = info.GetEnumerator();
162 while (e.MoveNext()) {
163 if (e.Name == "DataSet.RemotingFormat") {//DataSet.RemotingFormat does not exist in V1/V1.1 versions
164 remotingFormat = (SerializationFormat)e.Value;
165 break;
168 return (remotingFormat == SerializationFormat.Binary);
171 // Should Schema be included during Serialization
172 // 'static' function that consumes SerializationInfo
173 protected SchemaSerializationMode DetermineSchemaSerializationMode(SerializationInfo info, StreamingContext context) { //Typed DataSet calls into this
174 SchemaSerializationMode schemaSerializationMode = SchemaSerializationMode.IncludeSchema;
175 SerializationInfoEnumerator e = info.GetEnumerator();
177 while (e.MoveNext()) {
178 if (e.Name == "SchemaSerializationMode.DataSet") { //SchemaSerializationMode.DataSet does not exist in V1/V1.1 versions
179 schemaSerializationMode = (SchemaSerializationMode)e.Value;
180 break;
183 return schemaSerializationMode;
186 protected SchemaSerializationMode DetermineSchemaSerializationMode(XmlReader reader) { //Typed DataSet calls into this
187 SchemaSerializationMode schemaSerializationMode = SchemaSerializationMode.IncludeSchema;
188 reader.MoveToContent();
189 if (reader.NodeType == XmlNodeType.Element) {
190 if (reader.HasAttributes) {
191 string attribValue = reader.GetAttribute(Keywords.MSD_SCHEMASERIALIZATIONMODE, Keywords.MSDNS);
192 if ((String.Compare(attribValue, Keywords.MSD_EXCLUDESCHEMA, StringComparison.OrdinalIgnoreCase) == 0)) {
193 schemaSerializationMode = SchemaSerializationMode.ExcludeSchema;
195 else if ((String.Compare(attribValue, Keywords.MSD_INCLUDESCHEMA, StringComparison.OrdinalIgnoreCase) == 0)) {
196 schemaSerializationMode = SchemaSerializationMode.IncludeSchema;
198 else if (attribValue != null) { // if attrib does not exist, then don't throw
199 throw ExceptionBuilder.InvalidSchemaSerializationMode(typeof(SchemaSerializationMode), attribValue);
203 return schemaSerializationMode;
207 // Deserialize all the tables data of the dataset from binary/xml stream.
208 // 'instance' method that consumes SerializationInfo
209 protected void GetSerializationData(SerializationInfo info, StreamingContext context) {// mainly for typed DS
210 SerializationFormat remotingFormat = SerializationFormat.Xml;
211 SerializationInfoEnumerator e = info.GetEnumerator();
213 while (e.MoveNext()) {
214 if (e.Name == "DataSet.RemotingFormat") { //DataSet.RemotingFormat does not exist in V1/V1.1 versions
215 remotingFormat = (SerializationFormat)e.Value;
216 break;
219 DeserializeDataSetData(info, context, remotingFormat);
223 // Deserialize all the tables schema and data of the dataset from binary/xml stream.
224 protected DataSet(SerializationInfo info, StreamingContext context)
225 : this(info, context, true) {
227 protected DataSet(SerializationInfo info, StreamingContext context, bool ConstructSchema)
228 : this() {
229 SerializationFormat remotingFormat = SerializationFormat.Xml;
230 SchemaSerializationMode schemaSerializationMode = SchemaSerializationMode.IncludeSchema;
231 SerializationInfoEnumerator e = info.GetEnumerator();
233 while (e.MoveNext()) {
234 switch (e.Name) {
235 case "DataSet.RemotingFormat": //DataSet.RemotingFormat does not exist in V1/V1.1 versions
236 remotingFormat = (SerializationFormat)e.Value;
237 break;
238 case "SchemaSerializationMode.DataSet": //SchemaSerializationMode.DataSet does not exist in V1/V1.1 versions
239 schemaSerializationMode = (SchemaSerializationMode)e.Value;
240 break;
244 if (schemaSerializationMode == SchemaSerializationMode.ExcludeSchema) {
245 InitializeDerivedDataSet();
248 // adding back this check will fix typed dataset XML remoting, but we have to fix case that
249 // a class inherits from DataSet and just relies on DataSet to deserialize (see SQL BU DT 374717)
250 // to fix that case also, we need to add a flag and add it to below check so return (no-op) will be
251 // conditional (flag needs to be set in TypedDataSet
252 if (remotingFormat == SerializationFormat.Xml && !ConstructSchema /* && this.GetType() != typeof(DataSet)*/) {
253 return; //For typed dataset xml remoting, this is a no-op
255 DeserializeDataSet(info, context, remotingFormat, schemaSerializationMode);
260 [System.Security.Permissions.SecurityPermissionAttribute(System.Security.Permissions.SecurityAction.LinkDemand, Flags = System.Security.Permissions.SecurityPermissionFlag.SerializationFormatter)]
261 public virtual void GetObjectData(SerializationInfo info, StreamingContext context) {
262 SerializationFormat remotingFormat = RemotingFormat;
263 SerializeDataSet(info, context, remotingFormat);
266 // Deserialize all the tables data of the dataset from binary/xml stream.
267 protected virtual void InitializeDerivedDataSet() {
268 return;
271 // Serialize all the tables.
272 private void SerializeDataSet(SerializationInfo info, StreamingContext context, SerializationFormat remotingFormat) {
273 Debug.Assert(info != null);
274 info.AddValue("DataSet.RemotingVersion", new Version(2, 0));
276 // SqlHotFix 299, SerializationFormat enumeration types don't exist in V1.1 SP1
277 if (SerializationFormat.Xml != remotingFormat) {
278 info.AddValue("DataSet.RemotingFormat", remotingFormat);
281 // SqlHotFix 299, SchemaSerializationMode enumeration types don't exist in V1.1 SP1
282 if (SchemaSerializationMode.IncludeSchema != SchemaSerializationMode) {
283 //SkipSchemaDuringSerialization
284 info.AddValue("SchemaSerializationMode.DataSet", SchemaSerializationMode);
287 if (remotingFormat != SerializationFormat.Xml) {
288 if (SchemaSerializationMode == SchemaSerializationMode.IncludeSchema) {
290 //DataSet public state properties
291 SerializeDataSetProperties(info, context);
293 //Tables Count
294 info.AddValue("DataSet.Tables.Count", Tables.Count);
296 //Tables, Columns, Rows
297 for (int i = 0; i < Tables.Count; i++) {
298 BinaryFormatter bf = new BinaryFormatter(null, new StreamingContext(context.State, false));
299 MemoryStream memStream = new MemoryStream();
300 bf.Serialize(memStream, Tables[i]);
301 memStream.Position = 0;
302 info.AddValue(String.Format(CultureInfo.InvariantCulture, "DataSet.Tables_{0}", i), memStream.GetBuffer());
305 //Constraints
306 for (int i = 0; i < Tables.Count; i++) {
307 Tables[i].SerializeConstraints(info, context, i, true);
310 //Relations
311 SerializeRelations(info, context);
313 //Expression Columns
314 for (int i = 0; i < Tables.Count; i++) {
315 Tables[i].SerializeExpressionColumns(info, context, i);
318 else {
319 //Serialize DataSet public properties.
320 SerializeDataSetProperties(info, context);
322 //Rows
323 for (int i = 0; i < Tables.Count; i++) {
324 Tables[i].SerializeTableData(info, context, i);
326 } else { // old behaviour
328 String strSchema = this.GetXmlSchemaForRemoting(null);
330 String strData = null;
331 info.AddValue(KEY_XMLSCHEMA, strSchema);
333 StringBuilder strBuilder;
334 strBuilder = new StringBuilder(EstimatedXmlStringSize() * 2);
335 StringWriter strWriter = new StringWriter(strBuilder, CultureInfo.InvariantCulture);
336 XmlTextWriter w = new XmlTextWriter(strWriter);
337 WriteXml(w, XmlWriteMode.DiffGram);
338 strData = strWriter.ToString();
339 info.AddValue(KEY_XMLDIFFGRAM, strData);
343 // Deserialize all the tables - marked internal so that DataTable can call into this
344 internal void DeserializeDataSet(SerializationInfo info, StreamingContext context, SerializationFormat remotingFormat, SchemaSerializationMode schemaSerializationMode) {
345 // deserialize schema
346 DeserializeDataSetSchema(info, context, remotingFormat, schemaSerializationMode);
347 // deserialize data
348 DeserializeDataSetData(info, context, remotingFormat);
351 // Deserialize schema.
352 private void DeserializeDataSetSchema(SerializationInfo info, StreamingContext context, SerializationFormat remotingFormat, SchemaSerializationMode schemaSerializationMode) {
353 if (remotingFormat != SerializationFormat.Xml) {
354 if (schemaSerializationMode == SchemaSerializationMode.IncludeSchema) {
355 //DataSet public state properties
356 DeserializeDataSetProperties(info, context);
358 //Tables Count
359 int tableCount = info.GetInt32("DataSet.Tables.Count");
361 //Tables, Columns, Rows
362 for (int i = 0; i < tableCount; i++) {
363 Byte[] buffer = (Byte[])info.GetValue(String.Format(CultureInfo.InvariantCulture, "DataSet.Tables_{0}", i), typeof(Byte[]));
364 MemoryStream memStream = new MemoryStream(buffer);
365 memStream.Position = 0;
366 BinaryFormatter bf = new BinaryFormatter(null, new StreamingContext(context.State, false));
367 DataTable dt = (DataTable)bf.Deserialize(memStream);
368 Tables.Add(dt);
371 //Constraints
372 for (int i = 0; i < tableCount; i++) {
373 Tables[i].DeserializeConstraints(info, context, /* table index */i, /* serialize all constraints */ true); //
376 //Relations
377 DeserializeRelations(info, context);
379 //Expression Columns
380 for (int i = 0; i < tableCount; i++) {
381 Tables[i].DeserializeExpressionColumns(info, context, i);
383 } else {
384 //DeSerialize DataSet public properties.[Locale, CaseSensitive and EnforceConstraints]
385 DeserializeDataSetProperties(info, context);
387 } else {
388 string strSchema = (String)info.GetValue(KEY_XMLSCHEMA, typeof(System.String));
390 if (strSchema != null) {
391 this.ReadXmlSchema(new XmlTextReader(new StringReader(strSchema)), true);
396 // Deserialize all data.
397 private void DeserializeDataSetData(SerializationInfo info, StreamingContext context, SerializationFormat remotingFormat) {
398 if (remotingFormat != SerializationFormat.Xml) {
399 for (int i = 0; i < Tables.Count; i++) {
400 Tables[i].DeserializeTableData(info, context, i);
403 else {
404 string strData = (String)info.GetValue(KEY_XMLDIFFGRAM, typeof(System.String));
406 if (strData != null) {
407 this.ReadXml(new XmlTextReader(new StringReader(strData)), XmlReadMode.DiffGram);
412 // Serialize just the dataset properties
413 private void SerializeDataSetProperties(SerializationInfo info, StreamingContext context) {
414 //DataSet basic properties
415 info.AddValue("DataSet.DataSetName", DataSetName);
416 info.AddValue("DataSet.Namespace", Namespace);
417 info.AddValue("DataSet.Prefix", Prefix);
418 //DataSet runtime properties
419 info.AddValue("DataSet.CaseSensitive", CaseSensitive);
420 info.AddValue("DataSet.LocaleLCID", Locale.LCID);
421 info.AddValue("DataSet.EnforceConstraints", EnforceConstraints);
423 //ExtendedProperties
424 info.AddValue("DataSet.ExtendedProperties", ExtendedProperties);
427 // DeSerialize dataset properties
428 private void DeserializeDataSetProperties(SerializationInfo info, StreamingContext context) {
429 //DataSet basic properties
430 dataSetName = info.GetString("DataSet.DataSetName");
431 namespaceURI = info.GetString("DataSet.Namespace");
432 _datasetPrefix = info.GetString("DataSet.Prefix");
433 //DataSet runtime properties
434 _caseSensitive = info.GetBoolean("DataSet.CaseSensitive");
435 int lcid = (int)info.GetValue("DataSet.LocaleLCID", typeof(int));
436 _culture = new CultureInfo(lcid);
437 _cultureUserSet = true;
438 enforceConstraints = info.GetBoolean("DataSet.EnforceConstraints");
442 //ExtendedProperties
443 extendedProperties = (PropertyCollection)info.GetValue("DataSet.ExtendedProperties", typeof(PropertyCollection));
446 // Gets relation info from the dataset.
447 // ***Schema for Serializing ArrayList of Relations***
448 // Relations -> [relationName]->[parentTableIndex, parentcolumnIndexes]->[childTableIndex, childColumnIndexes]->[Nested]->[extendedProperties]
449 private void SerializeRelations(SerializationInfo info, StreamingContext context) {
450 ArrayList relationList = new ArrayList();
452 foreach (DataRelation rel in Relations) {
453 int[] parentInfo = new int[rel.ParentColumns.Length + 1];
455 parentInfo[0] = Tables.IndexOf(rel.ParentTable);
456 for (int j = 1; j < parentInfo.Length; j++) {
457 parentInfo[j] = rel.ParentColumns[j - 1].Ordinal;
460 int[] childInfo = new int[rel.ChildColumns.Length + 1];
461 childInfo[0] = Tables.IndexOf(rel.ChildTable);
462 for (int j = 1; j < childInfo.Length; j++) {
463 childInfo[j] = rel.ChildColumns[j - 1].Ordinal;
466 ArrayList list = new ArrayList();
467 list.Add(rel.RelationName);
468 list.Add(parentInfo);
469 list.Add(childInfo);
470 list.Add(rel.Nested);
471 list.Add(rel.extendedProperties);
473 relationList.Add(list);
475 info.AddValue("DataSet.Relations", relationList);
479 Adds relations to the dataset.
480 ***Schema for Serializing ArrayList of Relations***
481 Relations -> [relationName]->[parentTableIndex, parentcolumnIndexes]->[childTableIndex, childColumnIndexes]->[Nested]->[extendedProperties]
483 private void DeserializeRelations(SerializationInfo info, StreamingContext context) {
484 ArrayList relationList = (ArrayList)info.GetValue("DataSet.Relations", typeof(ArrayList));
486 foreach (ArrayList list in relationList) {
487 string relationName = (string)list[0];
488 int[] parentInfo = (int[])list[1];
489 int[] childInfo = (int[])list[2];
490 bool isNested = (bool)list[3];
491 PropertyCollection extendedProperties = (PropertyCollection)list[4];
493 //ParentKey Columns.
494 DataColumn[] parentkeyColumns = new DataColumn[parentInfo.Length - 1];
495 for (int i = 0; i < parentkeyColumns.Length; i++) {
496 parentkeyColumns[i] = Tables[parentInfo[0]].Columns[parentInfo[i + 1]];
499 //ChildKey Columns.
500 DataColumn[] childkeyColumns = new DataColumn[childInfo.Length - 1];
501 for (int i = 0; i < childkeyColumns.Length; i++) {
502 childkeyColumns[i] = Tables[childInfo[0]].Columns[childInfo[i + 1]];
505 //Create the Relation, without any constraints[Assumption: The constraints are added earlier than the relations]
506 DataRelation rel = new DataRelation(relationName, parentkeyColumns, childkeyColumns, false);
507 rel.CheckMultipleNested = false; // disable the check for multiple nested parent
508 rel.Nested = isNested;
509 rel.extendedProperties = extendedProperties;
511 Relations.Add(rel);
512 rel.CheckMultipleNested = true; // enable the check for multiple nested parent
516 internal void FailedEnableConstraints() {
517 this.EnforceConstraints = false;
518 throw ExceptionBuilder.EnforceConstraint();
521 /// <devdoc>
522 /// <para>
523 /// Gets or sets a value indicating whether string
524 /// comparisons within <see cref='System.Data.DataTable'/>
525 /// objects are
526 /// case-sensitive.
527 /// </para>
528 /// </devdoc>
530 ResCategoryAttribute(Res.DataCategory_Data),
531 DefaultValue(false),
532 ResDescriptionAttribute(Res.DataSetCaseSensitiveDescr)
534 public bool CaseSensitive {
535 get {
536 return _caseSensitive;
538 set {
539 if (_caseSensitive != value)
541 bool oldValue = _caseSensitive;
542 _caseSensitive = value;
544 if (!ValidateCaseConstraint()) {
545 _caseSensitive = oldValue;
546 throw ExceptionBuilder.CannotChangeCaseLocale();
549 foreach (DataTable table in Tables) {
550 table.SetCaseSensitiveValue(value, false, true);
556 bool System.ComponentModel.IListSource.ContainsListCollection {
557 get {
558 return true;
562 /// <devdoc>
563 /// <para>Gets a custom view of the data contained by the <see cref='System.Data.DataSet'/> , one
564 /// that allows filtering, searching, and navigating through the custom data view.</para>
565 /// </devdoc>
566 [Browsable(false), ResDescriptionAttribute(Res.DataSetDefaultViewDescr)]
567 public DataViewManager DefaultViewManager {
568 get {
569 if (defaultViewManager == null) {
570 lock (_defaultViewManagerLock) {
571 if (defaultViewManager == null) {
572 defaultViewManager = new DataViewManager(this, true);
576 return defaultViewManager;
580 /// <devdoc>
581 /// <para>Gets or sets a value indicating whether constraint rules are followed when
582 /// attempting any update operation.</para>
583 /// </devdoc>
584 [DefaultValue(true), ResDescriptionAttribute(Res.DataSetEnforceConstraintsDescr)]
585 public bool EnforceConstraints {
586 get {
587 return enforceConstraints;
589 set {
590 IntPtr hscp;
591 Bid.ScopeEnter(out hscp, "<ds.DataSet.set_EnforceConstraints|API> %d#, %d{bool}\n", ObjectID, value);
592 try {
593 if (this.enforceConstraints != value) {
594 if (value)
595 EnableConstraints();
596 this.enforceConstraints = value;
599 finally {
600 Bid.ScopeLeave(ref hscp);
605 internal void RestoreEnforceConstraints(bool value) {
606 this.enforceConstraints = value;
609 internal void EnableConstraints()
611 IntPtr hscp;
612 Bid.ScopeEnter(out hscp, "<ds.DataSet.EnableConstraints|INFO> %d#\n", ObjectID);
613 try {
614 bool errors = false;
615 for (ConstraintEnumerator constraints = new ConstraintEnumerator(this); constraints.GetNext(); ) {
616 Constraint constraint = (Constraint)constraints.GetConstraint();
617 errors |= constraint.IsConstraintViolated();
620 foreach (DataTable table in Tables) {
621 foreach (DataColumn column in table.Columns) {
622 if (!column.AllowDBNull) {
623 errors |= column.IsNotAllowDBNullViolated();
625 if (column.MaxLength >= 0) {
626 errors |= column.IsMaxLengthViolated();
631 if (errors)
632 this.FailedEnableConstraints();
634 finally {
635 Bid.ScopeLeave(ref hscp);
639 /// <devdoc>
640 /// <para>Gets or
641 /// sets the name of this <see cref='System.Data.DataSet'/> .</para>
642 /// </devdoc>
644 ResCategoryAttribute(Res.DataCategory_Data),
645 DefaultValue(""),
646 ResDescriptionAttribute(Res.DataSetDataSetNameDescr)
648 public string DataSetName {
649 get {
650 return dataSetName;
652 set {
653 Bid.Trace("<ds.DataSet.set_DataSetName|API> %d#, '%ls'\n", ObjectID, value);
654 if (value != dataSetName) {
655 if (value == null || value.Length == 0)
656 throw ExceptionBuilder.SetDataSetNameToEmpty();
657 DataTable conflicting = Tables[value, Namespace];
658 if ((conflicting != null) && (!conflicting.fNestedInDataset))
659 throw ExceptionBuilder.SetDataSetNameConflicting(value);
660 RaisePropertyChanging("DataSetName");
661 this.dataSetName = value;
666 /// <devdoc>
667 /// </devdoc>
669 DefaultValue(""),
670 ResCategoryAttribute(Res.DataCategory_Data),
671 ResDescriptionAttribute(Res.DataSetNamespaceDescr)
673 public string Namespace {
674 get {
675 return namespaceURI;
677 set {
678 Bid.Trace("<ds.DataSet.set_Namespace|API> %d#, '%ls'\n", ObjectID, value);
679 if (value == null)
680 value = String.Empty;
681 if (value != namespaceURI) {
682 RaisePropertyChanging("Namespace");
683 foreach (DataTable dt in Tables) {
684 if (dt.tableNamespace != null)
685 continue;
686 if ((dt.NestedParentRelations.Length == 0) ||
687 (dt.NestedParentRelations.Length == 1 && dt.NestedParentRelations[0].ChildTable == dt)) {
688 // dt.SelfNestedWithOneRelation) { // this is wrong bug it was previous behavior
689 if (Tables.Contains(dt.TableName, value, false, true))
690 throw ExceptionBuilder.DuplicateTableName2(dt.TableName, value);
691 dt.CheckCascadingNamespaceConflict(value);
692 dt.DoRaiseNamespaceChange();
695 namespaceURI = value;
698 if (Common.ADP.IsEmpty(value))
699 _datasetPrefix = String.Empty;
704 /// <devdoc>
705 /// <para>[To be supplied.]</para>
706 /// </devdoc>
708 DefaultValue(""),
709 ResCategoryAttribute(Res.DataCategory_Data),
710 ResDescriptionAttribute(Res.DataSetPrefixDescr)
712 public string Prefix {
713 get { return _datasetPrefix; }
714 set {
715 if (value == null)
716 value = String.Empty;
718 if ((XmlConvert.DecodeName(value) == value) &&
719 (XmlConvert.EncodeName(value) != value))
720 throw ExceptionBuilder.InvalidPrefix(value);
723 if (value != _datasetPrefix) {
724 RaisePropertyChanging("Prefix");
725 _datasetPrefix = value;
730 /// <devdoc>
731 /// <para>Gets the collection of custom user information.</para>
732 /// </devdoc>
734 ResCategoryAttribute(Res.DataCategory_Data),
735 Browsable(false),
736 ResDescriptionAttribute(Res.ExtendedPropertiesDescr)
738 public PropertyCollection ExtendedProperties {
739 get {
740 if (extendedProperties == null) {
741 extendedProperties = new PropertyCollection();
743 return extendedProperties;
747 /// <devdoc>
748 /// <para>
749 /// Gets a value indicating whether there are errors in any
750 /// of the rows in any of the tables of this <see cref='System.Data.DataSet'/> .
751 /// </para>
752 /// </devdoc>
753 [Browsable(false), ResDescriptionAttribute(Res.DataSetHasErrorsDescr)]
754 public bool HasErrors {
755 get {
756 for (int i = 0; i < Tables.Count; i++) {
757 if (Tables[i].HasErrors)
758 return true;
760 return false;
764 [Browsable(false)]
765 public bool IsInitialized {
766 get {
767 return !fInitInProgress;
771 /// <devdoc>
772 /// <para>
773 /// Gets or sets the locale information used to compare strings within the table.
774 /// </para>
775 /// </devdoc>
777 ResCategoryAttribute(Res.DataCategory_Data),
778 ResDescriptionAttribute(Res.DataSetLocaleDescr)
780 public CultureInfo Locale {
781 get {
782 // used for comparing not formating/parsing
783 Debug.Assert(null != _culture, "DataSet.Locale: null culture");
784 return _culture;
786 set {
787 IntPtr hscp;
788 Bid.ScopeEnter(out hscp, "<ds.DataSet.set_Locale|API> %d#\n", ObjectID);
789 try {
790 if (value != null) {
791 if (!_culture.Equals(value)) {
792 SetLocaleValue(value, true);
794 _cultureUserSet = true;
797 finally {
798 Bid.ScopeLeave(ref hscp);
803 internal void SetLocaleValue(CultureInfo value, bool userSet) {
804 bool flag = false;
805 bool exceptionThrown = false;
806 int tableCount = 0;
808 CultureInfo oldLocale = _culture;
809 bool oldUserSet = _cultureUserSet;
811 try {
812 _culture = value;
813 _cultureUserSet = userSet;
815 foreach (DataTable table in Tables) {
816 if (!table.ShouldSerializeLocale()) {
817 bool retchk = table.SetLocaleValue(value, false, false);
818 //Debug.Assert(retchk == table.ShouldSerializeLocale(), "unexpected setting of table locale"); may fire with Deserialize
822 flag = ValidateLocaleConstraint();
823 if (flag) {
824 flag = false;
825 foreach (DataTable table in Tables) {
826 tableCount++;
827 if (!table.ShouldSerializeLocale()) {
828 table.SetLocaleValue(value, false, true);
831 flag = true;
834 catch {
835 exceptionThrown = true;
836 throw;
838 finally {
839 if (!flag) { // reset old locale if ValidationFailed or exception thrown
840 _culture = oldLocale;
841 _cultureUserSet = oldUserSet;
842 foreach (DataTable table in Tables) {
843 if (!table.ShouldSerializeLocale()) {
844 table.SetLocaleValue(oldLocale, false, false);
847 try {
848 for (int i = 0; i < tableCount; ++i) {
849 if (!Tables[i].ShouldSerializeLocale()) {
850 Tables[i].SetLocaleValue(oldLocale, false, true);
854 catch (Exception e) {
855 if (!Common.ADP.IsCatchableExceptionType(e)) {
856 throw;
858 Common.ADP.TraceExceptionWithoutRethrow(e);
860 if (!exceptionThrown) {
861 throw ExceptionBuilder.CannotChangeCaseLocale(null);
867 internal bool ShouldSerializeLocale() {
868 // this method is used design-time scenarios via reflection
869 // by the property grid to show the Locale property in bold or not
870 // by the code dom for persisting the Locale property or not
872 // we always want the locale persisted if set by user or different the current thread
873 // but that logic should by performed by the serializion code
874 return _cultureUserSet;
877 /// <devdoc>
878 /// <para>[To be supplied.]</para>
879 /// </devdoc>
880 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
881 public override ISite Site {
882 get {
883 return base.Site;
885 set {
886 ISite oldSite = Site;
887 if (value == null && oldSite != null) {
888 IContainer cont = oldSite.Container;
890 if (cont != null) {
891 for (int i = 0; i < Tables.Count; i++) {
892 if (Tables[i].Site != null) {
893 cont.Remove(Tables[i]);
898 base.Site = value;
904 /// <devdoc>
905 /// <para>
906 /// Get the collection of relations that link tables and
907 /// allow navigation from parent tables to child tables.
908 /// </para>
909 /// </devdoc>
911 DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
912 ResCategoryAttribute(Res.DataCategory_Data),
913 ResDescriptionAttribute(Res.DataSetRelationsDescr)
915 public DataRelationCollection Relations {
916 get {
917 return relationCollection;
921 /// <devdoc>
922 /// <para>
923 /// Indicates whether <see cref='Relations'/> property should be persisted.
924 /// </para>
925 /// </devdoc>
926 protected virtual bool ShouldSerializeRelations() {
927 return true; /*Relations.Count > 0;*/ // VS7 300569
930 /// <devdoc>
931 /// <para>
932 /// Resets the <see cref='System.Data.DataSet.Relations'/> property to its default state.
933 /// </para>
934 /// </devdoc>
935 private void ResetRelations()
937 Relations.Clear();
940 /// <devdoc>
941 /// <para>Gets the collection of tables contained in the <see cref='System.Data.DataSet'/>.</para>
942 /// </devdoc>
944 DesignerSerializationVisibility(DesignerSerializationVisibility.Content),
945 ResCategoryAttribute(Res.DataCategory_Data),
946 ResDescriptionAttribute(Res.DataSetTablesDescr)
948 public DataTableCollection Tables {
949 get {
950 return tableCollection;
954 /// <devdoc>
955 /// <para>
956 /// Indicates whether <see cref='System.Data.DataSet.Tables'/> property should be persisted.
957 /// </para>
958 /// </devdoc>
959 protected virtual bool ShouldSerializeTables() {
960 return true;/*(Tables.Count > 0);*/ // VS7 300569
963 /// <devdoc>
964 /// <para>
965 /// Resets the <see cref='System.Data.DataSet.Tables'/> property to its default state.
966 /// </para>
967 /// </devdoc>
968 private void ResetTables()
970 Tables.Clear();
973 internal bool FBoundToDocument {
974 get {
975 return fBoundToDocument;
977 set {
978 fBoundToDocument = value;
982 /// <devdoc>
983 /// <para>
984 /// Commits all the changes made to this <see cref='System.Data.DataSet'/> since it was loaded or the last
985 /// time <see cref='System.Data.DataSet.AcceptChanges'/> was called.
986 /// </para>
987 /// </devdoc>
988 public void AcceptChanges()
990 IntPtr hscp;
991 Bid.ScopeEnter(out hscp, "<ds.DataSet.AcceptChanges|API> %d#\n", ObjectID);
992 try {
993 for (int i = 0; i < Tables.Count; i++)
994 Tables[i].AcceptChanges();
996 finally {
997 Bid.ScopeLeave(ref hscp);
1001 internal event PropertyChangedEventHandler PropertyChanging {
1002 add {
1003 onPropertyChangingDelegate += value;
1005 remove {
1006 onPropertyChangingDelegate -= value;
1010 /// <devdoc>
1011 /// <para>Occurs when attempting to merge schemas for two tables with the same
1012 /// name.</para>
1013 /// </devdoc>
1015 ResCategoryAttribute(Res.DataCategory_Action),
1016 ResDescriptionAttribute(Res.DataSetMergeFailedDescr)
1018 public event MergeFailedEventHandler MergeFailed {
1019 add {
1020 onMergeFailed += value;
1022 remove {
1023 onMergeFailed -= value;
1027 internal event DataRowCreatedEventHandler DataRowCreated {
1028 add {
1029 onDataRowCreated += value;
1031 remove {
1032 onDataRowCreated -= value;
1036 internal event DataSetClearEventhandler ClearFunctionCalled {
1037 add {
1038 onClearFunctionCalled += value;
1040 remove {
1041 onClearFunctionCalled -= value;
1046 ResCategoryAttribute(Res.DataCategory_Action),
1047 ResDescriptionAttribute(Res.DataSetInitializedDescr)
1049 public event System.EventHandler Initialized {
1050 add {
1051 onInitialized += value;
1053 remove {
1054 onInitialized -= value;
1058 public void BeginInit() {
1059 fInitInProgress = true;
1062 public void EndInit() {
1063 Tables.FinishInitCollection();
1064 for (int i = 0; i < Tables.Count; i++) {
1065 Tables[i].Columns.FinishInitCollection();
1068 for (int i = 0; i < Tables.Count; i++) {
1069 Tables[i].Constraints.FinishInitConstraints();
1072 ((DataRelationCollection.DataSetRelationCollection)Relations).FinishInitRelations();
1074 fInitInProgress = false;
1075 OnInitialized();
1078 /// <devdoc>
1079 /// <para>Clears the <see cref='System.Data.DataSet'/> of any data by removing all rows in all tables.</para>
1080 /// </devdoc>
1081 public void Clear()
1083 IntPtr hscp;
1084 Bid.ScopeEnter(out hscp, "<ds.DataSet.Clear|API> %d#\n", ObjectID);
1085 try {
1086 OnClearFunctionCalled(null);
1087 bool fEnforce = EnforceConstraints;
1088 EnforceConstraints = false;
1089 for (int i = 0; i < Tables.Count; i++)
1090 Tables[i].Clear();
1091 EnforceConstraints = fEnforce;
1093 finally {
1094 Bid.ScopeLeave(ref hscp);
1098 /// <devdoc>
1099 /// <para>Clones the structure of the <see cref='System.Data.DataSet'/>, including all <see cref='System.Data.DataTable'/> schemas, relations, and
1100 /// constraints.</para>
1101 /// </devdoc>
1102 // 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.
1103 [MethodImpl(MethodImplOptions.NoInlining)]
1104 public virtual DataSet Clone() {
1105 IntPtr hscp;
1106 Bid.ScopeEnter(out hscp, "<ds.DataSet.Clone|API> %d#\n", ObjectID);
1107 try {
1108 DataSet ds = (DataSet)Activator.CreateInstance(this.GetType(), true);
1110 if (ds.Tables.Count > 0) // Microsoft : To clean up all the schema in strong typed dataset.
1111 ds.Reset();
1113 //copy some original dataset properties
1114 ds.DataSetName = DataSetName;
1115 ds.CaseSensitive = CaseSensitive;
1116 ds._culture = _culture;
1117 ds._cultureUserSet = _cultureUserSet;
1118 ds.EnforceConstraints = EnforceConstraints;
1119 ds.Namespace = Namespace;
1120 ds.Prefix = Prefix;
1121 ds.RemotingFormat = RemotingFormat;
1122 ds.fIsSchemaLoading = true; //delay expression evaluation
1125 // ...Tables...
1126 DataTableCollection tbls = Tables;
1127 for (int i = 0; i < tbls.Count; i++) {
1128 DataTable dt = tbls[i].Clone(ds);
1129 dt.tableNamespace = tbls[i].Namespace; // hardcode the namespace for a second to not mess up
1130 // DataRelation cloning.
1131 ds.Tables.Add(dt);
1134 // ...Constraints...
1135 for (int i = 0; i < tbls.Count; i++) {
1136 ConstraintCollection constraints = tbls[i].Constraints;
1137 for (int j = 0; j < constraints.Count; j++) {
1138 if (constraints[j] is UniqueConstraint)
1139 continue;
1140 ForeignKeyConstraint foreign = constraints[j] as ForeignKeyConstraint;
1141 if (foreign.Table == foreign.RelatedTable)
1142 continue;// we have already added this foreign key in while cloning the datatable
1143 ds.Tables[i].Constraints.Add(constraints[j].Clone(ds));
1147 // ...Relations...
1148 DataRelationCollection rels = Relations;
1149 for (int i = 0; i < rels.Count; i++) {
1150 DataRelation rel = rels[i].Clone(ds);
1151 rel.CheckMultipleNested = false; // disable the check for multiple nested parent
1152 ds.Relations.Add(rel);
1153 rel.CheckMultipleNested = true; // enable the check for multiple nested parent
1156 // ...Extended Properties...
1157 if (this.extendedProperties != null) {
1158 foreach (Object key in this.extendedProperties.Keys) {
1159 ds.ExtendedProperties[key] = this.extendedProperties[key];
1163 foreach (DataTable table in Tables)
1164 foreach (DataColumn col in table.Columns)
1165 if (col.Expression.Length != 0)
1166 ds.Tables[table.TableName, table.Namespace].Columns[col.ColumnName].Expression = col.Expression;
1168 for (int i = 0; i < tbls.Count; i++) {
1169 ds.Tables[i].tableNamespace = tbls[i].tableNamespace; // undo the hardcoding of the namespace
1172 ds.fIsSchemaLoading = false; //reactivate column computations
1174 return ds;
1176 finally {
1177 Bid.ScopeLeave(ref hscp);
1181 /// <devdoc>
1182 /// <para>Copies both the structure and data for this <see cref='System.Data.DataSet'/>.</para>
1183 /// </devdoc>
1184 public DataSet Copy()
1186 IntPtr hscp;
1187 Bid.ScopeEnter(out hscp, "<ds.DataSet.Copy|API> %d#\n", ObjectID);
1188 try {
1189 DataSet dsNew = Clone();
1190 bool fEnforceConstraints = dsNew.EnforceConstraints;
1191 dsNew.EnforceConstraints = false;
1192 foreach (DataTable table in this.Tables)
1194 DataTable destTable = dsNew.Tables[table.TableName, table.Namespace];
1196 foreach (DataRow row in table.Rows)
1197 table.CopyRow(destTable, row);
1200 dsNew.EnforceConstraints = fEnforceConstraints;
1202 return dsNew;
1204 finally {
1205 Bid.ScopeLeave(ref hscp);
1209 internal Int32 EstimatedXmlStringSize()
1211 Int32 bytes = 100;
1212 for (int i = 0; i < Tables.Count; i++) {
1213 Int32 rowBytes = (Tables[i].TableName.Length + 4) << 2;
1214 DataTable table = Tables[i];
1215 for (int j = 0; j < table.Columns.Count; j++) {
1216 rowBytes += ((table.Columns[j].ColumnName.Length + 4) << 2);
1217 rowBytes += 20;
1219 bytes += table.Rows.Count * rowBytes;
1222 return bytes;
1225 /// <devdoc>
1226 /// <para>Returns a copy of the <see cref='System.Data.DataSet'/> that contains all changes made to
1227 /// it since it was loaded or <see cref='System.Data.DataSet.AcceptChanges'/>
1228 /// was last called.</para>
1229 /// </devdoc>
1230 public DataSet GetChanges()
1232 return GetChanges(DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);
1235 private struct TableChanges {
1236 private BitArray _rowChanges;
1237 private int _hasChanges;
1239 internal TableChanges(int rowCount) {
1240 _rowChanges = new BitArray(rowCount);
1241 _hasChanges = 0;
1243 internal int HasChanges {
1244 get { return _hasChanges; }
1245 set { _hasChanges = value; }
1247 internal bool this[int index] {
1248 get { return _rowChanges[index]; }
1249 set {
1250 Debug.Assert(value && !_rowChanges[index], "setting twice or to false");
1251 _rowChanges[index] = value;
1252 _hasChanges++;
1257 public DataSet GetChanges(DataRowState rowStates)
1259 IntPtr hscp;
1260 Bid.ScopeEnter(out hscp, "<ds.DataSet.GetChanges|API> %d#, rowStates=%d{ds.DataRowState}\n", ObjectID, (int)rowStates);
1261 try {
1262 DataSet dsNew = null;
1263 bool fEnforceConstraints = false;
1264 if (0 != (rowStates & ~(DataRowState.Added | DataRowState.Deleted | DataRowState.Modified | DataRowState.Unchanged))) {
1265 throw ExceptionBuilder.InvalidRowState(rowStates);
1268 // Initialize all the individual table bitmaps.
1269 TableChanges[] bitMatrix = new TableChanges[Tables.Count];
1270 for (int i = 0; i < bitMatrix.Length; ++i) {
1271 bitMatrix[i] = new TableChanges(Tables[i].Rows.Count);
1274 // find all the modified rows and their parents
1275 MarkModifiedRows(bitMatrix, rowStates);
1277 // copy the changes to a cloned table
1278 for (int i = 0; i < bitMatrix.Length; ++i) {
1279 Debug.Assert(0 <= bitMatrix[i].HasChanges, "negative change count");
1280 if (0 < bitMatrix[i].HasChanges) {
1281 if (null == dsNew) {
1282 dsNew = this.Clone();
1283 fEnforceConstraints = dsNew.EnforceConstraints;
1284 dsNew.EnforceConstraints = false;
1287 DataTable table = this.Tables[i];
1288 DataTable destTable = dsNew.Tables[table.TableName, table.Namespace];
1289 Debug.Assert(bitMatrix[i].HasChanges <= table.Rows.Count, "to many changes");
1291 for (int j = 0; 0 < bitMatrix[i].HasChanges; ++j) { // Loop through the rows.
1292 if (bitMatrix[i][j]) {
1293 table.CopyRow(destTable, table.Rows[j]);
1294 bitMatrix[i].HasChanges--;
1300 if (null != dsNew) {
1301 dsNew.EnforceConstraints = fEnforceConstraints;
1303 return dsNew;
1305 finally {
1306 Bid.ScopeLeave(ref hscp);
1310 private void MarkModifiedRows(TableChanges[] bitMatrix, DataRowState rowStates) {
1311 // for every table, every row & every relation find the modified rows and for non-deleted rows, their parents
1312 for (int tableIndex = 0; tableIndex < bitMatrix.Length; ++tableIndex) {
1313 DataRowCollection rows = Tables[tableIndex].Rows;
1314 int rowCount = rows.Count;
1316 for (int rowIndex = 0; rowIndex < rowCount; ++rowIndex) {
1317 DataRow row = rows[rowIndex];
1318 DataRowState rowState = row.RowState;
1319 Debug.Assert(DataRowState.Added == rowState ||
1320 DataRowState.Deleted == rowState ||
1321 DataRowState.Modified == rowState ||
1322 DataRowState.Unchanged == rowState,
1323 "unexpected DataRowState");
1325 // if bit not already set and row is modified
1326 if ((0 != (rowStates & rowState)) && !bitMatrix[tableIndex][rowIndex]) {
1327 bitMatrix[tableIndex][rowIndex] = true;
1329 if (DataRowState.Deleted != rowState) {
1330 MarkRelatedRowsAsModified(bitMatrix, row);
1337 private void MarkRelatedRowsAsModified(TableChanges[] bitMatrix, DataRow row) {
1338 DataRelationCollection relations = row.Table.ParentRelations;
1339 int relationCount = relations.Count;
1340 for (int relatedIndex = 0; relatedIndex < relationCount; ++relatedIndex) {
1341 DataRow[] relatedRows = row.GetParentRows(relations[relatedIndex], DataRowVersion.Current);
1343 foreach (DataRow relatedRow in relatedRows) {
1344 int relatedTableIndex = this.Tables.IndexOf(relatedRow.Table);
1345 int relatedRowIndex = relatedRow.Table.Rows.IndexOf(relatedRow);
1347 if (!bitMatrix[relatedTableIndex][relatedRowIndex]) {
1348 bitMatrix[relatedTableIndex][relatedRowIndex] = true;
1350 if (DataRowState.Deleted != relatedRow.RowState) {
1351 // recurse into related rows
1352 MarkRelatedRowsAsModified(bitMatrix, relatedRow);
1359 IList System.ComponentModel.IListSource.GetList() {
1360 return DefaultViewManager;
1363 internal string GetRemotingDiffGram(DataTable table)
1365 StringWriter strWriter = new StringWriter(CultureInfo.InvariantCulture);
1366 XmlTextWriter writer = new XmlTextWriter(strWriter);
1367 writer.Formatting = Formatting.Indented;
1368 if (strWriter != null) {
1369 // Create and save the updates
1370 new NewDiffgramGen(table, false).Save(writer, table);
1373 return strWriter.ToString();
1376 public string GetXml()
1378 IntPtr hscp;
1379 Bid.ScopeEnter(out hscp, "<ds.DataSet.GetXml|API> %d#\n", ObjectID);
1380 try {
1382 // StringBuilder strBuilder = new StringBuilder(EstimatedXmlStringSize());
1383 // StringWriter strWriter = new StringWriter(strBuilder);
1384 StringWriter strWriter = new StringWriter(CultureInfo.InvariantCulture);
1385 if (strWriter != null) {
1386 XmlTextWriter w = new XmlTextWriter(strWriter);
1387 w.Formatting = Formatting.Indented;
1388 new XmlDataTreeWriter(this).Save(w, false);
1390 return strWriter.ToString();
1392 finally {
1393 Bid.ScopeLeave(ref hscp);
1397 public string GetXmlSchema()
1399 IntPtr hscp;
1400 Bid.ScopeEnter(out hscp, "<ds.DataSet.GetXmlSchema|API> %d#\n", ObjectID);
1401 try {
1402 StringWriter strWriter = new StringWriter(CultureInfo.InvariantCulture);
1403 XmlTextWriter writer = new XmlTextWriter(strWriter);
1404 writer.Formatting = Formatting.Indented;
1405 if (strWriter != null) {
1406 (new XmlTreeGen(SchemaFormat.Public)).Save(this, writer);
1409 return strWriter.ToString();
1411 finally {
1412 Bid.ScopeLeave(ref hscp);
1416 internal string GetXmlSchemaForRemoting(DataTable table)
1418 StringWriter strWriter = new StringWriter(CultureInfo.InvariantCulture);
1419 XmlTextWriter writer = new XmlTextWriter(strWriter);
1420 writer.Formatting = Formatting.Indented;
1421 if (strWriter != null) {
1422 if (table == null) {
1423 if (this.SchemaSerializationMode == SchemaSerializationMode.ExcludeSchema)
1424 (new XmlTreeGen(SchemaFormat.RemotingSkipSchema)).Save(this, writer);
1425 else
1426 (new XmlTreeGen(SchemaFormat.Remoting)).Save(this, writer);
1428 else { // no skip schema support for typed datatable
1429 (new XmlTreeGen(SchemaFormat.Remoting)).Save(table, writer);
1433 return strWriter.ToString();
1437 /// <devdoc>
1438 /// <para>Gets a value indicating whether the <see cref='System.Data.DataSet'/> has changes, including new,
1439 /// deleted, or modified rows.</para>
1440 /// </devdoc>
1441 public bool HasChanges()
1443 return HasChanges(DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);
1446 /// <devdoc>
1447 /// <para>Gets a value indicating whether the <see cref='System.Data.DataSet'/> has changes, including new,
1448 /// deleted, or modified rows, filtered by <see cref='System.Data.DataRowState'/>.</para>
1449 /// </devdoc>
1450 public bool HasChanges(DataRowState rowStates)
1452 IntPtr hscp;
1453 Bid.ScopeEnter(out hscp, "<ds.DataSet.HasChanges|API> %d#, rowStates=%d{ds.DataRowState}\n", ObjectID, (int)rowStates);
1455 try {
1456 const DataRowState allRowStates = DataRowState.Detached | DataRowState.Unchanged | DataRowState.Added | DataRowState.Deleted | DataRowState.Modified;
1458 if ((rowStates & (~allRowStates)) != 0) {
1459 throw ExceptionBuilder.ArgumentOutOfRange("rowState");
1462 for (int i = 0; i < Tables.Count; i++) {
1463 DataTable table = Tables[i];
1465 for (int j = 0; j < table.Rows.Count; j++) {
1466 DataRow row = table.Rows[j];
1467 if ((row.RowState & rowStates) != 0) {
1468 return true;
1472 return false;
1474 finally {
1475 Bid.ScopeLeave(ref hscp);
1479 /// <devdoc>
1480 /// <para>Infer the XML schema from the specified <see cref='System.IO.TextReader'/> into the <see cref='System.Data.DataSet'/>.</para>
1481 /// </devdoc>
1482 public void InferXmlSchema(XmlReader reader, string[] nsArray)
1484 IntPtr hscp;
1485 Bid.ScopeEnter(out hscp, "<ds.DataSet.InferXmlSchema|API> %d#\n", ObjectID);
1486 try {
1487 if (reader == null)
1488 return;
1490 XmlDocument xdoc = new XmlDocument();
1491 if (reader.NodeType == XmlNodeType.Element) {
1492 XmlNode node = xdoc.ReadNode(reader);
1493 xdoc.AppendChild(node);
1495 else
1496 xdoc.Load(reader);
1497 if (xdoc.DocumentElement == null)
1498 return;
1500 InferSchema(xdoc, nsArray, XmlReadMode.InferSchema);
1502 finally {
1503 Bid.ScopeLeave(ref hscp);
1507 /// <devdoc>
1508 /// <para>Infer the XML schema from the specified <see cref='System.IO.TextReader'/> into the <see cref='System.Data.DataSet'/>.</para>
1509 /// </devdoc>
1510 public void InferXmlSchema(Stream stream, string[] nsArray)
1512 if (stream == null)
1513 return;
1515 InferXmlSchema(new XmlTextReader(stream), nsArray);
1518 /// <devdoc>
1519 /// <para>Infer the XML schema from the specified <see cref='System.IO.TextReader'/> into the <see cref='System.Data.DataSet'/>.</para>
1520 /// </devdoc>
1521 public void InferXmlSchema(TextReader reader, string[] nsArray)
1523 if (reader == null)
1524 return;
1526 InferXmlSchema(new XmlTextReader(reader), nsArray);
1529 /// <devdoc>
1530 /// <para>Infer the XML schema from the specified file into the <see cref='System.Data.DataSet'/>.</para>
1531 /// </devdoc>
1532 [ResourceExposure(ResourceScope.Machine)]
1533 [ResourceConsumption(ResourceScope.Machine)]
1534 public void InferXmlSchema(String fileName, string[] nsArray)
1536 XmlTextReader xr = new XmlTextReader(fileName);
1537 try {
1538 InferXmlSchema(xr, nsArray);
1540 finally {
1541 xr.Close();
1545 /// <devdoc>
1546 /// <para>Reads the XML schema from the specified <see cref='T:System.Xml.XMLReader'/> into the <see cref='System.Data.DataSet'/>
1547 /// .</para>
1548 /// </devdoc>
1549 public void ReadXmlSchema(XmlReader reader)
1551 ReadXmlSchema(reader, false);
1554 internal void ReadXmlSchema(XmlReader reader, bool denyResolving)
1556 IntPtr hscp;
1557 Bid.ScopeEnter(out hscp, "<ds.DataSet.ReadXmlSchema|INFO> %d#, reader, denyResolving=%d{bool}\n", ObjectID, denyResolving);
1558 try {
1559 int iCurrentDepth = -1;
1561 if (reader == null)
1562 return;
1564 if (reader is XmlTextReader)
1565 ((XmlTextReader)reader).WhitespaceHandling = WhitespaceHandling.None;
1567 XmlDocument xdoc = new XmlDocument(); // we may need this to infer the schema
1569 if (reader.NodeType == XmlNodeType.Element)
1570 iCurrentDepth = reader.Depth;
1572 reader.MoveToContent();
1574 if (reader.NodeType == XmlNodeType.Element) {
1575 // if reader points to the schema load it...
1577 if (reader.LocalName == Keywords.XDR_SCHEMA && reader.NamespaceURI == Keywords.XDRNS) {
1578 // load XDR schema and exit
1579 ReadXDRSchema(reader);
1580 return;
1583 if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI == Keywords.XSDNS) {
1584 // load XSD schema and exit
1585 ReadXSDSchema(reader, denyResolving);
1586 return;
1589 if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI.StartsWith(Keywords.XSD_NS_START, StringComparison.Ordinal))
1590 throw ExceptionBuilder.DataSetUnsupportedSchema(Keywords.XSDNS);
1592 // ... otherwise backup the top node and all its attributes
1593 XmlElement topNode = xdoc.CreateElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
1594 if (reader.HasAttributes) {
1595 int attrCount = reader.AttributeCount;
1596 for (int i = 0; i < attrCount; i++) {
1597 reader.MoveToAttribute(i);
1598 if (reader.NamespaceURI.Equals(Keywords.XSD_XMLNS_NS))
1599 topNode.SetAttribute(reader.Name, reader.GetAttribute(i));
1600 else {
1601 XmlAttribute attr = topNode.SetAttributeNode(reader.LocalName, reader.NamespaceURI);
1602 attr.Prefix = reader.Prefix;
1603 attr.Value = reader.GetAttribute(i);
1607 reader.Read();
1609 while (MoveToElement(reader, iCurrentDepth)) {
1611 // if reader points to the schema load it...
1612 if (reader.LocalName == Keywords.XDR_SCHEMA && reader.NamespaceURI == Keywords.XDRNS) {
1613 // load XDR schema and exit
1614 ReadXDRSchema(reader);
1615 return;
1618 if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI == Keywords.XSDNS) {
1619 // load XSD schema and exit
1620 ReadXSDSchema(reader, denyResolving);
1621 return;
1624 if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI.StartsWith(Keywords.XSD_NS_START, StringComparison.Ordinal))
1625 throw ExceptionBuilder.DataSetUnsupportedSchema(Keywords.XSDNS);
1628 XmlNode node = xdoc.ReadNode(reader);
1629 topNode.AppendChild(node);
1633 // read the closing tag of the current element
1634 ReadEndElement(reader);
1636 // if we are here no schema has been found
1637 xdoc.AppendChild(topNode);
1639 // so we InferSchema
1640 InferSchema(xdoc, null, XmlReadMode.Auto);
1643 finally {
1644 Bid.ScopeLeave(ref hscp);
1648 internal bool MoveToElement(XmlReader reader, int depth) {
1649 while (!reader.EOF && reader.NodeType != XmlNodeType.EndElement && reader.NodeType != XmlNodeType.Element && reader.Depth > depth) {
1650 reader.Read();
1652 return (reader.NodeType == XmlNodeType.Element);
1655 private static void MoveToElement(XmlReader reader) {
1656 while (!reader.EOF && reader.NodeType != XmlNodeType.EndElement && reader.NodeType != XmlNodeType.Element) {
1657 reader.Read();
1660 internal void ReadEndElement(XmlReader reader) {
1661 while (reader.NodeType == XmlNodeType.Whitespace) {
1662 reader.Skip();
1664 if (reader.NodeType == XmlNodeType.None) {
1665 reader.Skip();
1667 else if (reader.NodeType == XmlNodeType.EndElement) {
1668 reader.ReadEndElement();
1672 internal void ReadXSDSchema(XmlReader reader, bool denyResolving) {
1673 XmlSchemaSet sSet = new XmlSchemaSet();
1675 int schemaFragmentCount = 1;
1676 //read from current schmema element
1677 if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI == Keywords.XSDNS) {
1678 if (reader.HasAttributes) {
1679 string attribValue = reader.GetAttribute(Keywords.MSD_FRAGMENTCOUNT, Keywords.MSDNS); // this must not move the position
1680 if (!Common.ADP.IsEmpty(attribValue)) {
1681 schemaFragmentCount = int.Parse(attribValue, null);
1686 while (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI == Keywords.XSDNS) {
1687 XmlSchema s = XmlSchema.Read(reader, null);
1688 sSet.Add(s);
1689 //read the end tag
1690 ReadEndElement(reader);
1692 if (--schemaFragmentCount > 0) {
1693 MoveToElement(reader);
1695 while (reader.NodeType == XmlNodeType.Whitespace) {
1696 reader.Skip();
1699 sSet.Compile();
1700 XSDSchema schema = new XSDSchema();
1701 schema.LoadSchema(sSet, this);
1704 internal void ReadXDRSchema(XmlReader reader) {
1705 XmlDocument xdoc = new XmlDocument(); // we may need this to infer the schema
1706 XmlNode schNode = xdoc.ReadNode(reader);
1707 xdoc.AppendChild(schNode);
1708 XDRSchema schema = new XDRSchema(this, false);
1709 this.DataSetName = xdoc.DocumentElement.LocalName;
1710 schema.LoadSchema((XmlElement)schNode, this);
1713 /// <devdoc>
1714 /// <para>Reads the XML schema from the specified <see cref='System.IO.Stream'/> into the
1715 /// <see cref='System.Data.DataSet'/>.</para>
1716 /// </devdoc>
1717 public void ReadXmlSchema(Stream stream)
1719 if (stream == null)
1720 return;
1722 ReadXmlSchema(new XmlTextReader(stream), false);
1725 /// <devdoc>
1726 /// <para>Reads the XML schema from the specified <see cref='System.IO.TextReader'/> into the <see cref='System.Data.DataSet'/>.</para>
1727 /// </devdoc>
1728 public void ReadXmlSchema(TextReader reader)
1730 if (reader == null)
1731 return;
1733 ReadXmlSchema(new XmlTextReader(reader), false);
1736 /// <devdoc>
1737 /// <para>Reads the XML schema from the specified file into the <see cref='System.Data.DataSet'/>.</para>
1738 /// </devdoc>
1739 [ResourceExposure(ResourceScope.Machine)]
1740 [ResourceConsumption(ResourceScope.Machine)]
1741 public void ReadXmlSchema(String fileName)
1743 XmlTextReader xr = new XmlTextReader(fileName);
1744 try {
1745 ReadXmlSchema(xr, false);
1747 finally {
1748 xr.Close();
1752 #region WriteXmlSchema
1753 /// <summary>Writes the <see cref='DataSet'/> structure as an XML schema to using the specified <see cref='Stream'/> object.</summary>
1754 /// <param name="stream">A <see cref='Stream'/> object used to write to a file.</param>
1755 public void WriteXmlSchema(Stream stream)
1757 this.WriteXmlSchema(stream, SchemaFormat.Public, (Converter<Type, string>)null);
1760 /// <summary>Writes the <see cref='DataSet'/> structure as an XML schema to using the specified <see cref='Stream'/> object.</summary>
1761 /// <param name="stream">A <see cref='Stream'/> object used to write to a file.</param>
1762 /// <param name="multipleTargetConverter">A delegate used to convert <see cref='Type'/> into string.</param>
1763 public void WriteXmlSchema(Stream stream, Converter<Type, string> multipleTargetConverter)
1765 ADP.CheckArgumentNull(multipleTargetConverter, "multipleTargetConverter");
1766 this.WriteXmlSchema(stream, SchemaFormat.Public, multipleTargetConverter);
1769 /// <summary>Writes the <see cref='DataSet'/> structure as an XML schema to a file.</summary>
1770 /// <param name="fileName">The file name (including the path) to which to write.</param>
1771 [ResourceExposure(ResourceScope.Machine)]
1772 [ResourceConsumption(ResourceScope.Machine)]
1773 public void WriteXmlSchema(String fileName)
1775 this.WriteXmlSchema(fileName, SchemaFormat.Public, (Converter<Type, string>)null);
1778 /// <summary>Writes the <see cref='DataSet'/> structure as an XML schema to a file.</summary>
1779 /// <param name="fileName">The file name (including the path) to which to write.</param>
1780 /// <param name="multipleTargetConverter">A delegate used to convert <see cref='Type'/> into string.</param>
1781 [ResourceExposure(ResourceScope.Machine)]
1782 [ResourceConsumption(ResourceScope.Machine)]
1783 public void WriteXmlSchema(String fileName, Converter<Type, string> multipleTargetConverter)
1785 ADP.CheckArgumentNull(multipleTargetConverter, "multipleTargetConverter");
1786 this.WriteXmlSchema(fileName, SchemaFormat.Public, multipleTargetConverter);
1789 /// <summary>Writes the <see cref='DataSet'/> structure as an XML schema to a <see cref='TextWriter'/> object.</summary>
1790 /// <param name="writer">The <see cref='TextWriter'/> object with which to write.</param>
1791 public void WriteXmlSchema(TextWriter writer)
1793 this.WriteXmlSchema(writer, SchemaFormat.Public, (Converter<Type, string>)null);
1796 /// <summary>Writes the <see cref='DataSet'/> structure as an XML schema to a <see cref='TextWriter'/> object.</summary>
1797 /// <param name="writer">The <see cref='TextWriter'/> object with which to write.</param>
1798 /// <param name="multipleTargetConverter">A delegate used to convert <see cref='Type'/> into string.</param>
1799 public void WriteXmlSchema(TextWriter writer, Converter<Type, string> multipleTargetConverter)
1801 ADP.CheckArgumentNull(multipleTargetConverter, "multipleTargetConverter");
1802 this.WriteXmlSchema(writer, SchemaFormat.Public, multipleTargetConverter);
1805 /// <summary>Writes the <see cref='DataSet'/> structure as an XML schema to an <see cref='XmlWriter'/> object.</summary>
1806 /// <param name="writer">The <see cref='XmlWriter'/> object with which to write.</param>
1807 public void WriteXmlSchema(XmlWriter writer)
1809 this.WriteXmlSchema(writer, SchemaFormat.Public, (Converter<Type, string>)null);
1812 /// <summary>Writes the <see cref='DataSet'/> structure as an XML schema to an <see cref='XmlWriter'/> object.</summary>
1813 /// <param name="writer">The <see cref='XmlWriter'/> object with which to write.</param>
1814 /// <param name="multipleTargetConverter">A delegate used to convert <see cref='Type'/> into string.</param>
1815 public void WriteXmlSchema(XmlWriter writer, Converter<Type, string> multipleTargetConverter)
1817 ADP.CheckArgumentNull(multipleTargetConverter, "multipleTargetConverter");
1818 this.WriteXmlSchema(writer, SchemaFormat.Public, multipleTargetConverter);
1821 [ResourceExposure(ResourceScope.Machine)]
1822 [ResourceConsumption(ResourceScope.Machine)]
1823 private void WriteXmlSchema(String fileName, SchemaFormat schemaFormat, Converter<Type, string> multipleTargetConverter)
1825 XmlTextWriter xw = new XmlTextWriter( fileName, null );
1826 try {
1827 xw.Formatting = Formatting.Indented;
1828 xw.WriteStartDocument(true);
1829 this.WriteXmlSchema(xw, schemaFormat, multipleTargetConverter);
1830 xw.WriteEndDocument();
1832 finally {
1833 xw.Close();
1837 private void WriteXmlSchema(Stream stream, SchemaFormat schemaFormat, Converter<Type, string> multipleTargetConverter)
1839 if (stream == null)
1840 return;
1842 XmlTextWriter w = new XmlTextWriter(stream, null);
1843 w.Formatting = Formatting.Indented;
1845 this.WriteXmlSchema(w, schemaFormat, multipleTargetConverter);
1848 private void WriteXmlSchema(TextWriter writer, SchemaFormat schemaFormat, Converter<Type, string> multipleTargetConverter)
1850 if (writer == null)
1851 return;
1853 XmlTextWriter w = new XmlTextWriter(writer);
1854 w.Formatting = Formatting.Indented;
1856 this.WriteXmlSchema(w, schemaFormat, multipleTargetConverter);
1859 private void WriteXmlSchema(XmlWriter writer, SchemaFormat schemaFormat, Converter<Type, string> multipleTargetConverter)
1861 IntPtr hscp;
1862 Bid.ScopeEnter(out hscp, "<ds.DataSet.WriteXmlSchema|INFO> %d#, schemaFormat=%d{ds.SchemaFormat}\n", ObjectID, (int)schemaFormat);
1863 try {
1864 // Generate SchemaTree and write it out
1865 if (writer != null) {
1866 XmlTreeGen treeGen = null;
1867 if (schemaFormat == SchemaFormat.WebService &&
1868 SchemaSerializationMode == SchemaSerializationMode.ExcludeSchema &&
1869 writer.WriteState == WriteState.Element) {
1870 treeGen = new XmlTreeGen(SchemaFormat.WebServiceSkipSchema);
1872 else {
1873 treeGen = new XmlTreeGen(schemaFormat);
1876 treeGen.Save(this, (DataTable)null, writer, false, multipleTargetConverter);
1879 finally {
1880 Bid.ScopeLeave(ref hscp);
1883 #endregion
1885 /// <devdoc>
1886 /// </devdoc>
1887 public XmlReadMode ReadXml(XmlReader reader)
1889 return ReadXml(reader, false);
1893 internal XmlReadMode ReadXml(XmlReader reader, bool denyResolving)
1895 IntPtr hscp;
1896 Bid.ScopeEnter(out hscp, "<ds.DataSet.ReadXml|INFO> %d#, denyResolving=%d{bool}\n", ObjectID, denyResolving);
1897 try {
1899 DataTable.DSRowDiffIdUsageSection rowDiffIdUsage = new DataTable.DSRowDiffIdUsageSection();
1900 try {
1901 bool fDataFound = false;
1902 bool fSchemaFound = false;
1903 bool fDiffsFound = false;
1904 bool fIsXdr = false;
1905 int iCurrentDepth = -1;
1906 XmlReadMode ret = XmlReadMode.Auto;
1907 bool isEmptyDataSet = false;
1908 bool topNodeIsProcessed = false; // we chanche topnode and there is just one case that we miss to process it
1909 // it is : <elem attrib1="Attrib">txt</elem>
1911 // clear the hashtable to avoid conflicts between diffgrams, SqlHotFix 782
1912 rowDiffIdUsage.Prepare(this);
1914 if (reader == null)
1915 return ret;
1917 if (Tables.Count == 0) {
1918 isEmptyDataSet = true;
1921 if (reader is XmlTextReader)
1922 ((XmlTextReader)reader).WhitespaceHandling = WhitespaceHandling.Significant;
1924 XmlDocument xdoc = new XmlDocument(); // we may need this to infer the schema
1925 XmlDataLoader xmlload = null;
1928 reader.MoveToContent();
1930 if (reader.NodeType == XmlNodeType.Element)
1931 iCurrentDepth = reader.Depth;
1933 if (reader.NodeType == XmlNodeType.Element) {
1934 if ((reader.LocalName == Keywords.DIFFGRAM) && (reader.NamespaceURI == Keywords.DFFNS)) {
1935 this.ReadXmlDiffgram(reader);
1936 // read the closing tag of the current element
1937 ReadEndElement(reader);
1938 return XmlReadMode.DiffGram;
1941 // if reader points to the schema load it
1942 if (reader.LocalName == Keywords.XDR_SCHEMA && reader.NamespaceURI == Keywords.XDRNS) {
1943 // load XDR schema and exit
1944 ReadXDRSchema(reader);
1945 return XmlReadMode.ReadSchema; //since the top level element is a schema return
1948 if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI == Keywords.XSDNS) {
1949 // load XSD schema and exit
1950 ReadXSDSchema(reader, denyResolving);
1951 return XmlReadMode.ReadSchema; //since the top level element is a schema return
1954 if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI.StartsWith(Keywords.XSD_NS_START, StringComparison.Ordinal))
1955 throw ExceptionBuilder.DataSetUnsupportedSchema(Keywords.XSDNS);
1957 // now either the top level node is a table and we load it through dataReader...
1959 // ... or backup the top node and all its attributes because we may need to InferSchema
1960 XmlElement topNode = xdoc.CreateElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
1961 if (reader.HasAttributes) {
1962 int attrCount = reader.AttributeCount;
1963 for (int i = 0; i < attrCount; i++) {
1964 reader.MoveToAttribute(i);
1965 if (reader.NamespaceURI.Equals(Keywords.XSD_XMLNS_NS))
1966 topNode.SetAttribute(reader.Name, reader.GetAttribute(i));
1967 else {
1968 XmlAttribute attr = topNode.SetAttributeNode(reader.LocalName, reader.NamespaceURI);
1969 attr.Prefix = reader.Prefix;
1970 attr.Value = reader.GetAttribute(i);
1974 reader.Read();
1975 string rootNodeSimpleContent = reader.Value;
1977 while (MoveToElement(reader, iCurrentDepth)) {
1979 if ((reader.LocalName == Keywords.DIFFGRAM) && (reader.NamespaceURI == Keywords.DFFNS)) {
1980 this.ReadXmlDiffgram(reader);
1981 // read the closing tag of the current element
1982 // YUKON FIX ReadEndElement(reader);
1983 // return XmlReadMode.DiffGram;
1984 ret = XmlReadMode.DiffGram; // continue reading for multiple schemas
1987 // if reader points to the schema load it...
1990 if (!fSchemaFound && !fDataFound && reader.LocalName == Keywords.XDR_SCHEMA && reader.NamespaceURI == Keywords.XDRNS) {
1991 // load XDR schema and exit
1992 ReadXDRSchema(reader);
1993 fSchemaFound = true;
1994 fIsXdr = true;
1995 continue;
1998 if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI == Keywords.XSDNS) {
1999 // load XSD schema and exit
2000 ReadXSDSchema(reader, denyResolving);
2001 fSchemaFound = true;
2002 continue;
2005 if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI.StartsWith(Keywords.XSD_NS_START, StringComparison.Ordinal))
2006 throw ExceptionBuilder.DataSetUnsupportedSchema(Keywords.XSDNS);
2008 if ((reader.LocalName == Keywords.DIFFGRAM) && (reader.NamespaceURI == Keywords.DFFNS)) {
2009 this.ReadXmlDiffgram(reader);
2010 fDiffsFound = true;
2011 ret = XmlReadMode.DiffGram;
2013 else {
2014 // We have found data IFF the reader.NodeType == Element and reader.depth == currentDepth-1
2015 // if reader.NodeType == whitespace, skip all white spaces.
2016 // skip processing i.e. continue if the first non-whitespace node is not of type element.
2017 while (!reader.EOF && reader.NodeType == XmlNodeType.Whitespace)
2018 reader.Read();
2019 if (reader.NodeType != XmlNodeType.Element)
2020 continue;
2021 // we found data here
2022 fDataFound = true;
2024 if (!fSchemaFound && Tables.Count == 0) {
2025 XmlNode node = xdoc.ReadNode(reader);
2026 topNode.AppendChild(node);
2028 else {
2029 if (xmlload == null)
2030 xmlload = new XmlDataLoader(this, fIsXdr, topNode, false);
2031 xmlload.LoadData(reader);
2032 topNodeIsProcessed = true; // we process the topnode
2033 if (fSchemaFound)
2034 ret = XmlReadMode.ReadSchema;
2035 else
2036 ret = XmlReadMode.IgnoreSchema;
2041 // read the closing tag of the current element
2042 ReadEndElement(reader);
2043 bool isfTopLevelTableSet = false;
2044 bool tmpValue = this.fTopLevelTable;
2045 //While inference we ignore root elements text content
2046 if (!fSchemaFound && Tables.Count == 0 && !topNode.HasChildNodes) { //We shoule not come add SC of root elemnt to topNode if we are not infering
2047 this.fTopLevelTable = true;
2048 isfTopLevelTableSet = true;
2049 if ((rootNodeSimpleContent != null && rootNodeSimpleContent.Length > 0))
2050 topNode.InnerText = rootNodeSimpleContent;
2052 if (!isEmptyDataSet) {
2053 if ((rootNodeSimpleContent != null && rootNodeSimpleContent.Length > 0))
2054 topNode.InnerText = rootNodeSimpleContent;
2057 // now top node contains the data part
2058 xdoc.AppendChild(topNode);
2060 if (xmlload == null)
2061 xmlload = new XmlDataLoader(this, fIsXdr, topNode, false);
2063 if (!isEmptyDataSet && !topNodeIsProcessed) {
2064 XmlElement root = xdoc.DocumentElement;
2065 Debug.Assert(root.NamespaceURI != null, "root.NamespaceURI should not ne null, it should be empty string");
2066 // just recognize that below given Xml represents datatable in toplevel
2067 //<table attr1="foo" attr2="bar" table_Text="junk">text</table>
2068 // only allow root element with simple content, if any
2069 if (root.ChildNodes.Count == 0 ||
2070 ((root.ChildNodes.Count == 1) && root.FirstChild.GetType() == typeof(System.Xml.XmlText))) {
2071 bool initfTopLevelTable = this.fTopLevelTable;
2072 // if root element maps to a datatable
2073 // ds and dt cant have the samm name and ns at the same time, how to write to xml
2074 if (this.DataSetName != root.Name && this.namespaceURI != root.NamespaceURI &&
2075 Tables.Contains(root.Name, (root.NamespaceURI.Length == 0) ? null : root.NamespaceURI, false, true)) {
2076 this.fTopLevelTable = true;
2078 try {
2079 xmlload.LoadData(xdoc);
2081 finally {
2082 this.fTopLevelTable = initfTopLevelTable; // this is not for inference, we have schema and we were skipping
2083 // topnode where it was a datatable, We must restore the value
2086 }// above check and below check are orthogonal
2087 // so we InferSchema
2088 if (!fDiffsFound) {
2089 // Load Data
2090 if (!fSchemaFound && Tables.Count == 0) {
2091 InferSchema(xdoc, null, XmlReadMode.Auto);
2092 ret = XmlReadMode.InferSchema;
2093 xmlload.FromInference = true;
2094 try {
2095 xmlload.LoadData(xdoc);
2097 finally {
2098 xmlload.FromInference = false;
2101 //We dont need this assignement. Once we set it(where we set it during inference), it won't be changed
2102 if (isfTopLevelTableSet)
2103 this.fTopLevelTable = tmpValue;
2107 return ret;
2109 finally {
2110 rowDiffIdUsage.Cleanup();
2113 finally {
2114 Bid.ScopeLeave(ref hscp);
2119 /// <devdoc>
2120 /// </devdoc>
2121 public XmlReadMode ReadXml(Stream stream)
2123 if (stream == null)
2124 return XmlReadMode.Auto;
2126 XmlTextReader xr = new XmlTextReader(stream);
2128 // Prevent Dtd entity in dataset
2129 xr.XmlResolver = null;
2131 return ReadXml(xr, false);
2134 /// <devdoc>
2135 /// </devdoc>
2136 public XmlReadMode ReadXml(TextReader reader)
2138 if (reader == null)
2139 return XmlReadMode.Auto;
2141 XmlTextReader xr = new XmlTextReader(reader);
2143 // Prevent Dtd entity in dataset
2144 xr.XmlResolver = null;
2146 return ReadXml(xr, false);
2149 /// <devdoc>
2150 /// </devdoc>
2151 [ResourceExposure(ResourceScope.Machine)]
2152 [ResourceConsumption(ResourceScope.Machine)]
2153 public XmlReadMode ReadXml(string fileName)
2155 XmlTextReader xr = new XmlTextReader(fileName);
2157 // Prevent Dtd entity in dataset
2158 xr.XmlResolver = null;
2162 return ReadXml(xr, false);
2164 finally {
2165 xr.Close();
2169 internal void InferSchema(XmlDocument xdoc, string[] excludedNamespaces, XmlReadMode mode) {
2170 IntPtr hscp;
2171 Bid.ScopeEnter(out hscp, "<ds.DataSet.InferSchema|INFO> %d#, mode=%d{ds.XmlReadMode}\n", ObjectID, (int)mode);
2172 try {
2173 string ns = xdoc.DocumentElement.NamespaceURI;
2174 if (null == excludedNamespaces) {
2175 excludedNamespaces = new string[0];
2177 XmlNodeReader xnr = new XmlIgnoreNamespaceReader(xdoc, excludedNamespaces);
2178 System.Xml.Schema.XmlSchemaInference infer = new System.Xml.Schema.XmlSchemaInference();
2180 infer.Occurrence = XmlSchemaInference.InferenceOption.Relaxed;
2182 if (mode == XmlReadMode.InferTypedSchema)
2183 infer.TypeInference = XmlSchemaInference.InferenceOption.Restricted;
2184 else
2185 infer.TypeInference = XmlSchemaInference.InferenceOption.Relaxed;
2187 XmlSchemaSet schemaSet = infer.InferSchema(xnr);
2188 schemaSet.Compile();
2190 XSDSchema schema = new XSDSchema();
2191 schema.FromInference = true;
2193 try {
2194 schema.LoadSchema(schemaSet, this);
2196 finally {
2197 schema.FromInference = false; // this is always false if you are not calling fron inference
2200 finally {
2201 Bid.ScopeLeave(ref hscp);
2205 private bool IsEmpty() {
2206 foreach (DataTable table in this.Tables)
2207 if (table.Rows.Count > 0)
2208 return false;
2209 return true;
2212 private void ReadXmlDiffgram(XmlReader reader) {
2213 IntPtr hscp;
2214 Bid.ScopeEnter(out hscp, "<ds.DataSet.ReadXmlDiffgram|INFO> %d#\n", ObjectID);
2215 try {
2216 int d = reader.Depth;
2217 bool fEnforce = this.EnforceConstraints;
2218 this.EnforceConstraints = false;
2219 DataSet newDs;
2220 bool isEmpty = this.IsEmpty();
2222 if (isEmpty) {
2223 newDs = this;
2225 else {
2226 newDs = this.Clone();
2227 newDs.EnforceConstraints = false;
2230 foreach (DataTable t in newDs.Tables) {
2231 t.Rows.nullInList = 0;
2233 reader.MoveToContent();
2234 if ((reader.LocalName != Keywords.DIFFGRAM) && (reader.NamespaceURI != Keywords.DFFNS))
2235 return;
2236 reader.Read();
2237 if (reader.NodeType == XmlNodeType.Whitespace)
2238 MoveToElement(reader, reader.Depth - 1 /*iCurrentDepth*/); // skip over whitespaces.
2240 newDs.fInLoadDiffgram = true;
2242 if (reader.Depth > d) {
2243 if ((reader.NamespaceURI != Keywords.DFFNS) && (reader.NamespaceURI != Keywords.MSDNS)) {
2244 //we should be inside the dataset part
2245 XmlDocument xdoc = new XmlDocument();
2246 XmlElement node = xdoc.CreateElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
2247 reader.Read();
2248 if (reader.NodeType == XmlNodeType.Whitespace) {
2249 MoveToElement(reader, reader.Depth - 1 /*iCurrentDepth*/); // skip over whitespaces.
2251 if (reader.Depth - 1 > d) {
2252 XmlDataLoader xmlload = new XmlDataLoader(newDs, false, node, false);
2253 xmlload.isDiffgram = true; // turn on the special processing
2254 xmlload.LoadData(reader);
2256 ReadEndElement(reader);
2257 if (reader.NodeType == XmlNodeType.Whitespace) {
2258 MoveToElement(reader, reader.Depth - 1 /*iCurrentDepth*/); // skip over whitespaces.
2261 Debug.Assert(reader.NodeType != XmlNodeType.Whitespace, "Should not be on Whitespace node");
2263 if (((reader.LocalName == Keywords.SQL_BEFORE) && (reader.NamespaceURI == Keywords.DFFNS)) ||
2264 ((reader.LocalName == Keywords.MSD_ERRORS) && (reader.NamespaceURI == Keywords.DFFNS)))
2267 //this will consume the changes and the errors part
2268 XMLDiffLoader diffLoader = new XMLDiffLoader();
2269 diffLoader.LoadDiffGram(newDs, reader);
2272 // get to the closing diff tag
2273 while (reader.Depth > d) {
2274 reader.Read();
2276 // read the closing tag
2277 ReadEndElement(reader);
2280 foreach (DataTable t in newDs.Tables) {
2281 if (t.Rows.nullInList > 0)
2282 throw ExceptionBuilder.RowInsertMissing(t.TableName);
2285 newDs.fInLoadDiffgram = false;
2287 //terrible performance!
2288 foreach (DataTable t in newDs.Tables) {
2289 DataRelation[] nestedParentRelations = t.NestedParentRelations;
2290 foreach (DataRelation rel in nestedParentRelations) {
2291 if (rel.ParentTable == t) {
2292 foreach (DataRow r in t.Rows) {
2293 foreach (DataRelation rel2 in nestedParentRelations) {
2294 r.CheckForLoops(rel2);
2301 if (!isEmpty) {
2302 this.Merge(newDs);
2303 if (this.dataSetName == "NewDataSet")
2304 this.dataSetName = newDs.dataSetName;
2305 newDs.EnforceConstraints = fEnforce;
2307 this.EnforceConstraints = fEnforce;
2309 finally {
2310 Bid.ScopeLeave(ref hscp);
2315 /// <devdoc>
2316 /// </devdoc>
2317 public XmlReadMode ReadXml(XmlReader reader, XmlReadMode mode)
2319 return ReadXml(reader, mode, false);
2322 internal XmlReadMode ReadXml(XmlReader reader, XmlReadMode mode, bool denyResolving)
2324 IntPtr hscp;
2325 Bid.ScopeEnter(out hscp, "<ds.DataSet.ReadXml|INFO> %d#, mode=%d{ds.XmlReadMode}, denyResolving=%d{bool}\n", ObjectID, (int)mode, denyResolving);
2326 try {
2328 XmlReadMode ret = mode;
2330 if (reader == null)
2331 return ret;
2333 if (mode == XmlReadMode.Auto) {
2334 // Dev11 915079: nested ReadXml calls on the same DataSet must be done outside of RowDiffIdUsage scope
2335 return ReadXml(reader);
2338 DataTable.DSRowDiffIdUsageSection rowDiffIdUsage = new DataTable.DSRowDiffIdUsageSection();
2339 try {
2341 bool fSchemaFound = false;
2342 bool fDataFound = false;
2343 bool fIsXdr = false;
2344 int iCurrentDepth = -1;
2346 // Dev11 904428: prepare and cleanup rowDiffId hashtable
2347 rowDiffIdUsage.Prepare(this);
2349 if (reader is XmlTextReader)
2350 ((XmlTextReader)reader).WhitespaceHandling = WhitespaceHandling.Significant;
2352 XmlDocument xdoc = new XmlDocument(); // we may need this to infer the schema
2354 if ((mode != XmlReadMode.Fragment) && (reader.NodeType == XmlNodeType.Element))
2355 iCurrentDepth = reader.Depth;
2357 reader.MoveToContent();
2358 XmlDataLoader xmlload = null;
2360 if (reader.NodeType == XmlNodeType.Element) {
2361 XmlElement topNode = null;
2362 if (mode == XmlReadMode.Fragment) {
2363 xdoc.AppendChild(xdoc.CreateElement("ds_sqlXmlWraPPeR"));
2364 topNode = xdoc.DocumentElement;
2366 else { //handle the top node
2367 if ((reader.LocalName == Keywords.DIFFGRAM) && (reader.NamespaceURI == Keywords.DFFNS)) {
2368 if ((mode == XmlReadMode.DiffGram) || (mode == XmlReadMode.IgnoreSchema)) {
2369 this.ReadXmlDiffgram(reader);
2370 // read the closing tag of the current element
2371 ReadEndElement(reader);
2373 else {
2374 reader.Skip();
2376 return ret;
2379 if (reader.LocalName == Keywords.XDR_SCHEMA && reader.NamespaceURI == Keywords.XDRNS) {
2380 // load XDR schema and exit
2381 if ((mode != XmlReadMode.IgnoreSchema) && (mode != XmlReadMode.InferSchema) &&
2382 (mode != XmlReadMode.InferTypedSchema))
2384 ReadXDRSchema(reader);
2386 else {
2387 reader.Skip();
2389 return ret; //since the top level element is a schema return
2392 if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI == Keywords.XSDNS) {
2393 // load XSD schema and exit
2394 if ((mode != XmlReadMode.IgnoreSchema) && (mode != XmlReadMode.InferSchema) &&
2395 (mode != XmlReadMode.InferTypedSchema))
2397 ReadXSDSchema(reader, denyResolving);
2399 else
2400 reader.Skip();
2401 return ret; //since the top level element is a schema return
2404 if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI.StartsWith(Keywords.XSD_NS_START, StringComparison.Ordinal))
2405 throw ExceptionBuilder.DataSetUnsupportedSchema(Keywords.XSDNS);
2407 // now either the top level node is a table and we load it through dataReader...
2408 // ... or backup the top node and all its attributes
2409 topNode = xdoc.CreateElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
2410 if (reader.HasAttributes) {
2411 int attrCount = reader.AttributeCount;
2412 for (int i = 0; i < attrCount; i++) {
2413 reader.MoveToAttribute(i);
2414 if (reader.NamespaceURI.Equals(Keywords.XSD_XMLNS_NS))
2415 topNode.SetAttribute(reader.Name, reader.GetAttribute(i));
2416 else {
2417 XmlAttribute attr = topNode.SetAttributeNode(reader.LocalName, reader.NamespaceURI);
2418 attr.Prefix = reader.Prefix;
2419 attr.Value = reader.GetAttribute(i);
2423 reader.Read();
2426 while (MoveToElement(reader, iCurrentDepth)) {
2428 if (reader.LocalName == Keywords.XDR_SCHEMA && reader.NamespaceURI == Keywords.XDRNS) {
2429 // load XDR schema
2430 if (!fSchemaFound && !fDataFound && (mode != XmlReadMode.IgnoreSchema) && (mode != XmlReadMode.InferSchema) &&
2431 (mode != XmlReadMode.InferTypedSchema))
2433 ReadXDRSchema(reader);
2434 fSchemaFound = true;
2435 fIsXdr = true;
2437 else {
2438 reader.Skip();
2440 continue;
2443 if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI == Keywords.XSDNS) {
2444 // load XSD schema and exit
2445 if ((mode != XmlReadMode.IgnoreSchema) && (mode != XmlReadMode.InferSchema) &&
2446 (mode != XmlReadMode.InferTypedSchema))
2448 ReadXSDSchema(reader, denyResolving);
2449 fSchemaFound = true;
2451 else {
2452 reader.Skip();
2454 continue;
2457 if ((reader.LocalName == Keywords.DIFFGRAM) && (reader.NamespaceURI == Keywords.DFFNS)) {
2458 if ((mode == XmlReadMode.DiffGram) || (mode == XmlReadMode.IgnoreSchema)) {
2459 this.ReadXmlDiffgram(reader);
2460 ret = XmlReadMode.DiffGram;
2462 else {
2463 reader.Skip();
2465 continue;
2468 if (reader.LocalName == Keywords.XSD_SCHEMA && reader.NamespaceURI.StartsWith(Keywords.XSD_NS_START, StringComparison.Ordinal))
2469 throw ExceptionBuilder.DataSetUnsupportedSchema(Keywords.XSDNS);
2471 if (mode == XmlReadMode.DiffGram) {
2472 reader.Skip();
2473 continue; // we do not read data in diffgram mode
2476 // if we are here we found some data
2477 fDataFound = true;
2479 if (mode == XmlReadMode.InferSchema || mode == XmlReadMode.InferTypedSchema) { //save the node in DOM until the end;
2480 XmlNode node = xdoc.ReadNode(reader);
2481 topNode.AppendChild(node);
2483 else {
2484 if (xmlload == null)
2485 xmlload = new XmlDataLoader(this, fIsXdr, topNode, mode == XmlReadMode.IgnoreSchema);
2486 xmlload.LoadData(reader);
2488 } //end of the while
2490 // read the closing tag of the current element
2491 ReadEndElement(reader);
2493 // now top node contains the data part
2494 xdoc.AppendChild(topNode);
2495 if (xmlload == null)
2496 xmlload = new XmlDataLoader(this, fIsXdr, mode == XmlReadMode.IgnoreSchema);
2498 if (mode == XmlReadMode.DiffGram) {
2499 // we already got the diffs through XmlReader interface
2500 return ret;
2503 // Load Data
2504 if (mode == XmlReadMode.InferSchema || mode == XmlReadMode.InferTypedSchema) {
2505 InferSchema(xdoc, null, mode);
2506 ret = XmlReadMode.InferSchema;
2507 xmlload.FromInference = true;
2508 // }
2509 try {
2510 xmlload.LoadData(xdoc);
2512 finally {
2513 xmlload.FromInference = false;
2518 return ret;
2520 finally {
2521 // Dev11 904428: prepare and cleanup rowDiffId hashtable
2522 rowDiffIdUsage.Cleanup();
2525 finally {
2526 Bid.ScopeLeave(ref hscp);
2531 /// <devdoc>
2532 /// </devdoc>
2533 public XmlReadMode ReadXml(Stream stream, XmlReadMode mode)
2535 if (stream == null)
2536 return XmlReadMode.Auto;
2538 XmlTextReader reader = (mode == XmlReadMode.Fragment) ? new XmlTextReader(stream, XmlNodeType.Element, null) : new XmlTextReader(stream);
2539 // Prevent Dtd entity in dataset
2540 reader.XmlResolver = null;
2541 return ReadXml(reader, mode, false);
2544 /// <devdoc>
2545 /// </devdoc>
2546 public XmlReadMode ReadXml(TextReader reader, XmlReadMode mode)
2548 if (reader == null)
2549 return XmlReadMode.Auto;
2551 XmlTextReader xmlreader = (mode == XmlReadMode.Fragment) ? new XmlTextReader(reader.ReadToEnd(), XmlNodeType.Element, null) : new XmlTextReader(reader);
2552 // Prevent Dtd entity in dataset
2553 xmlreader.XmlResolver = null;
2554 return ReadXml(xmlreader, mode, false);
2557 /// <devdoc>
2558 /// </devdoc>
2559 [ResourceExposure(ResourceScope.Machine)]
2560 [ResourceConsumption(ResourceScope.Machine)]
2561 public XmlReadMode ReadXml(string fileName, XmlReadMode mode)
2563 XmlTextReader xr = null;
2564 if (mode == XmlReadMode.Fragment) {
2565 FileStream stream = new FileStream(fileName, FileMode.Open);
2566 xr = new XmlTextReader(stream, XmlNodeType.Element, null);
2568 else
2569 xr = new XmlTextReader(fileName);
2571 // Prevent Dtd entity in dataset
2572 xr.XmlResolver = null;
2576 return ReadXml(xr, mode, false);
2578 finally {
2579 xr.Close();
2584 /// <devdoc>
2585 /// Writes schema and data for the DataSet.
2586 /// </devdoc>
2587 public void WriteXml(Stream stream)
2589 WriteXml(stream, XmlWriteMode.IgnoreSchema);
2592 /// <devdoc>
2593 /// </devdoc>
2594 public void WriteXml(TextWriter writer)
2596 WriteXml(writer, XmlWriteMode.IgnoreSchema);
2599 /// <devdoc>
2600 /// </devdoc>
2601 public void WriteXml(XmlWriter writer)
2603 WriteXml(writer, XmlWriteMode.IgnoreSchema);
2606 /// <devdoc>
2607 /// <para>[To be supplied.]</para>
2608 /// </devdoc>
2609 [ResourceExposure(ResourceScope.Machine)]
2610 [ResourceConsumption(ResourceScope.Machine)]
2611 public void WriteXml(String fileName)
2613 WriteXml(fileName, XmlWriteMode.IgnoreSchema);
2616 /// <devdoc>
2617 /// Writes schema and data for the DataSet.
2618 /// </devdoc>
2619 public void WriteXml(Stream stream, XmlWriteMode mode)
2621 if (stream != null) {
2622 XmlTextWriter w = new XmlTextWriter(stream, null);
2623 w.Formatting = Formatting.Indented;
2625 WriteXml(w, mode);
2629 /// <devdoc>
2630 /// </devdoc>
2631 public void WriteXml(TextWriter writer, XmlWriteMode mode)
2633 if (writer != null) {
2634 XmlTextWriter w = new XmlTextWriter(writer);
2635 w.Formatting = Formatting.Indented;
2637 WriteXml(w, mode);
2641 /// <devdoc>
2642 /// </devdoc>
2643 public void WriteXml(XmlWriter writer, XmlWriteMode mode)
2645 IntPtr hscp;
2646 Bid.ScopeEnter(out hscp, "<ds.DataSet.WriteXml|API> %d#, mode=%d{ds.XmlWriteMode}\n", ObjectID, (int)mode);
2647 try {
2648 // Generate SchemaTree and write it out
2649 if (writer != null) {
2651 if (mode == XmlWriteMode.DiffGram) {
2652 // Create and save the updates
2653 // new UpdateTreeGen(UpdateTreeGen.UPDATE, (DataRowState)(-1), this).Save(writer, null);
2654 new NewDiffgramGen(this).Save(writer);
2656 else {
2657 // Create and save xml data
2658 new XmlDataTreeWriter(this).Save(writer, mode == XmlWriteMode.WriteSchema);
2662 finally {
2663 Bid.ScopeLeave(ref hscp);
2667 /// <devdoc>
2668 /// <para>[To be supplied.]</para>
2669 /// </devdoc>
2670 [ResourceExposure(ResourceScope.Machine)]
2671 [ResourceConsumption(ResourceScope.Machine)]
2672 public void WriteXml(String fileName, XmlWriteMode mode)
2674 IntPtr hscp;
2675 Bid.ScopeEnter(out hscp, "<ds.DataSet.WriteXml|API> %d#, fileName='%ls', mode=%d{ds.XmlWriteMode}\n", ObjectID, fileName, (int)mode);
2676 XmlTextWriter xw = new XmlTextWriter(fileName, null);
2677 try {
2678 xw.Formatting = Formatting.Indented;
2679 xw.WriteStartDocument(true);
2680 if (xw != null) {
2681 // Create and save the updates
2682 if (mode == XmlWriteMode.DiffGram) {
2683 new NewDiffgramGen(this).Save(xw);
2685 else {
2686 // Create and save xml data
2687 new XmlDataTreeWriter(this).Save(xw, mode == XmlWriteMode.WriteSchema);
2690 xw.WriteEndDocument();
2692 finally {
2693 xw.Close();
2694 Bid.ScopeLeave(ref hscp);
2698 /// <devdoc>
2699 /// <para>
2700 /// Gets the collection of parent relations which belong to a
2701 /// specified table.
2702 /// </para>
2703 /// </devdoc>
2704 internal DataRelationCollection GetParentRelations(DataTable table)
2706 return table.ParentRelations;
2709 /// <devdoc>
2710 /// <para>
2711 /// Merges this <see cref='System.Data.DataSet'/> into a specified <see cref='System.Data.DataSet'/>.
2712 /// </para>
2713 /// </devdoc>
2714 public void Merge(DataSet dataSet)
2716 IntPtr hscp;
2717 Bid.ScopeEnter(out hscp, "<ds.DataSet.Merge|API> %d#, dataSet=%d\n", ObjectID, (dataSet != null) ? dataSet.ObjectID : 0);
2718 try {
2719 Merge(dataSet, false, MissingSchemaAction.Add);
2721 finally {
2722 Bid.ScopeLeave(ref hscp);
2726 /// <devdoc>
2727 /// <para>
2728 /// Merges this <see cref='System.Data.DataSet'/> into a specified <see cref='System.Data.DataSet'/> preserving changes according to
2729 /// the specified argument.
2730 /// </para>
2731 /// </devdoc>
2732 public void Merge(DataSet dataSet, bool preserveChanges)
2734 IntPtr hscp;
2735 Bid.ScopeEnter(out hscp, "<ds.DataSet.Merge|API> %d#, dataSet=%d, preserveChanges=%d{bool}\n", ObjectID, (dataSet != null) ? dataSet.ObjectID : 0, preserveChanges);
2736 try {
2737 Merge(dataSet, preserveChanges, MissingSchemaAction.Add);
2739 finally {
2740 Bid.ScopeLeave(ref hscp);
2744 /// <devdoc>
2745 /// <para>
2746 /// Merges this <see cref='System.Data.DataSet'/> into a specified <see cref='System.Data.DataSet'/> preserving changes according to
2747 /// the specified argument, and handling an incompatible schema according to the
2748 /// specified argument.
2749 /// </para>
2750 /// </devdoc>
2751 public void Merge(DataSet dataSet, bool preserveChanges, MissingSchemaAction missingSchemaAction) {
2752 IntPtr hscp;
2753 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);
2754 try {
2756 // Argument checks
2757 if (dataSet == null)
2758 throw ExceptionBuilder.ArgumentNull("dataSet");
2760 switch (missingSchemaAction) { // @perfnote: Enum.IsDefined
2761 case MissingSchemaAction.Add:
2762 case MissingSchemaAction.Ignore:
2763 case MissingSchemaAction.Error:
2764 case MissingSchemaAction.AddWithKey:
2765 Merger merger = new Merger(this, preserveChanges, missingSchemaAction);
2766 merger.MergeDataSet(dataSet);
2767 break;
2768 default:
2769 throw Common.ADP.InvalidMissingSchemaAction(missingSchemaAction);
2772 finally {
2773 Bid.ScopeLeave(ref hscp);
2777 /// <devdoc>
2778 /// <para>
2779 /// Merges this <see cref='System.Data.DataTable'/> into a specified <see cref='System.Data.DataTable'/>.
2780 /// </para>
2781 /// </devdoc>
2782 public void Merge(DataTable table)
2784 IntPtr hscp;
2785 Bid.ScopeEnter(out hscp, "<ds.DataSet.Merge|API> %d#, table=%d\n", ObjectID, (table != null) ? table.ObjectID : 0);
2786 try {
2787 Merge(table, false, MissingSchemaAction.Add);
2789 finally {
2790 Bid.ScopeLeave(ref hscp);
2794 /// <devdoc>
2795 /// <para>
2796 /// Merges this <see cref='System.Data.DataTable'/> into a specified <see cref='System.Data.DataTable'/>. with a value to preserve changes
2797 /// made to the target, and a value to deal with missing schemas.
2798 /// </para>
2799 /// </devdoc>
2800 public void Merge(DataTable table, bool preserveChanges, MissingSchemaAction missingSchemaAction)
2802 IntPtr hscp;
2803 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);
2804 try {
2805 // Argument checks
2806 if (table == null)
2807 throw ExceptionBuilder.ArgumentNull("table");
2809 switch (missingSchemaAction) { // @perfnote: Enum.IsDefined
2810 case MissingSchemaAction.Add:
2811 case MissingSchemaAction.Ignore:
2812 case MissingSchemaAction.Error:
2813 case MissingSchemaAction.AddWithKey:
2814 Merger merger = new Merger(this, preserveChanges, missingSchemaAction);
2815 merger.MergeTable(table);
2816 break;
2817 default:
2818 throw Common.ADP.InvalidMissingSchemaAction(missingSchemaAction);
2821 finally {
2822 Bid.ScopeLeave(ref hscp);
2827 /// <devdoc>
2828 /// <para>[To be supplied.]</para>
2829 /// </devdoc>
2830 public void Merge(DataRow[] rows)
2832 IntPtr hscp;
2833 Bid.ScopeEnter(out hscp, "<ds.DataSet.Merge|API> %d#, rows\n", ObjectID);
2834 try {
2835 Merge(rows, false, MissingSchemaAction.Add);
2837 finally {
2838 Bid.ScopeLeave(ref hscp);
2842 /// <devdoc>
2843 /// <para>[To be supplied.]</para>
2844 /// </devdoc>
2845 public void Merge(DataRow[] rows, bool preserveChanges, MissingSchemaAction missingSchemaAction)
2847 IntPtr hscp;
2848 Bid.ScopeEnter(out hscp, "<ds.DataSet.Merge|API> %d#, preserveChanges=%d{bool}, missingSchemaAction=%d{ds.MissingSchemaAction}\n", ObjectID, preserveChanges, (int)missingSchemaAction);
2849 try {
2850 // Argument checks
2851 if (rows == null)
2852 throw ExceptionBuilder.ArgumentNull("rows");
2854 switch (missingSchemaAction) { // @perfnote: Enum.IsDefined
2855 case MissingSchemaAction.Add:
2856 case MissingSchemaAction.Ignore:
2857 case MissingSchemaAction.Error:
2858 case MissingSchemaAction.AddWithKey:
2859 Merger merger = new Merger(this, preserveChanges, missingSchemaAction);
2860 merger.MergeRows(rows);
2861 break;
2862 default:
2863 throw Common.ADP.InvalidMissingSchemaAction(missingSchemaAction);
2866 finally {
2867 Bid.ScopeLeave(ref hscp);
2871 protected virtual void OnPropertyChanging(PropertyChangedEventArgs pcevent)
2873 if (onPropertyChangingDelegate != null)
2874 onPropertyChangingDelegate(this, pcevent);
2877 /// <devdoc>
2878 /// Inheriting classes should override this method to handle this event.
2879 /// Call base.OnMergeFailed to send this event to any registered event
2880 /// listeners.
2881 /// </devdoc>
2882 internal void OnMergeFailed(MergeFailedEventArgs mfevent)
2884 if (onMergeFailed != null)
2885 onMergeFailed(this, mfevent);
2886 else
2887 throw ExceptionBuilder.MergeFailed(mfevent.Conflict);
2890 internal void RaiseMergeFailed(DataTable table, string conflict, MissingSchemaAction missingSchemaAction)
2892 if (MissingSchemaAction.Error == missingSchemaAction)
2893 throw ExceptionBuilder.MergeFailed(conflict);
2895 MergeFailedEventArgs mfevent = new MergeFailedEventArgs(table, conflict);
2896 OnMergeFailed(mfevent);
2897 return;
2900 internal void OnDataRowCreated(DataRow row) {
2901 if (onDataRowCreated != null)
2902 onDataRowCreated(this, row);
2905 internal void OnClearFunctionCalled(DataTable table) {
2906 if (onClearFunctionCalled != null)
2907 onClearFunctionCalled(this, table);
2910 private void OnInitialized() {
2911 if (onInitialized != null) {
2912 onInitialized(this, EventArgs.Empty);
2916 /// <devdoc>
2917 /// This method should be overriden by subclasses to restrict tables being removed.
2918 /// </devdoc>
2919 protected internal virtual void OnRemoveTable(DataTable table) {
2922 internal void OnRemovedTable(DataTable table) {
2923 DataViewManager viewManager = defaultViewManager;
2924 if (null != viewManager) {
2925 viewManager.DataViewSettings.Remove(table);
2929 /// <devdoc>
2930 /// This method should be overriden by subclasses to restrict tables being removed.
2931 /// </devdoc>
2932 protected virtual void OnRemoveRelation(DataRelation relation)
2937 internal void OnRemoveRelationHack(DataRelation relation)
2939 OnRemoveRelation(relation);
2943 protected internal void RaisePropertyChanging(string name)
2945 OnPropertyChanging(new PropertyChangedEventArgs(name));
2948 internal DataTable[] TopLevelTables()
2950 return TopLevelTables(false);
2953 internal DataTable[] TopLevelTables(bool forSchema)
2955 // first let's figure out if we can represent the given dataSet as a tree using
2956 // the fact that all connected undirected graphs with n-1 edges are trees.
2957 List<DataTable> topTables = new List<DataTable>();
2959 if (forSchema) {
2960 // prepend the tables that are nested more than once
2961 for (int i = 0; i < Tables.Count; i++)
2963 DataTable table = Tables[i];
2964 if (table.NestedParentsCount > 1 || table.SelfNested)
2965 topTables.Add(table);
2968 for (int i = 0; i < Tables.Count; i++)
2970 DataTable table = Tables[i];
2971 if (table.NestedParentsCount == 0 && !topTables.Contains(table))
2972 topTables.Add(table);
2974 if (topTables.Count == 0)
2975 return zeroTables;
2976 return topTables.ToArray();
2979 /// <devdoc>
2980 /// This method rolls back all the changes to have been made to this DataSet since
2981 /// it was loaded or the last time AcceptChanges was called.
2982 /// Any rows still in edit-mode cancel their edits. New rows get removed. Modified and
2983 /// Deleted rows return back to their original state.
2984 /// </devdoc>
2985 public virtual void RejectChanges()
2987 IntPtr hscp;
2988 Bid.ScopeEnter(out hscp, "<ds.DataSet.RejectChanges|API> %d#\n", ObjectID);
2989 try {
2990 bool fEnforce = EnforceConstraints;
2991 EnforceConstraints = false;
2992 for (int i = 0; i < Tables.Count; i++)
2993 Tables[i].RejectChanges();
2994 EnforceConstraints = fEnforce;
2996 finally {
2997 Bid.ScopeLeave(ref hscp);
3001 /// <devdoc>
3002 /// Resets the dataSet back to it's original state. Subclasses should override
3003 /// to restore back to it's original state.
3004 ///
3006 public virtual void Reset()
3008 IntPtr hscp;
3009 Bid.ScopeEnter(out hscp, "<ds.DataSet.Reset|API> %d#\n", ObjectID);
3010 try {
3011 for (int i = 0; i < Tables.Count; i++) {
3012 ConstraintCollection cons = Tables[i].Constraints;
3013 for (int j = 0; j < cons.Count; ) {
3014 if (cons[j] is ForeignKeyConstraint) {
3015 cons.Remove(cons[j]);
3017 else
3018 j++;
3021 // SQLBU 502734: because of SQLBU 501916, dependent tables need to be notified when a table is cleared
3022 // if relations are removed first, then exceptions happen
3023 Clear();
3024 Relations.Clear();
3025 Tables.Clear();
3027 finally {
3028 Bid.ScopeLeave(ref hscp);
3032 internal bool ValidateCaseConstraint() {
3033 IntPtr hscp;
3034 Bid.ScopeEnter(out hscp, "<ds.DataSet.ValidateCaseConstraint|INFO> %d#\n", ObjectID);
3035 try {
3036 DataRelation relation = null;
3037 for (int i = 0; i < Relations.Count; i++) {
3038 relation = Relations[i];
3039 if (relation.ChildTable.CaseSensitive != relation.ParentTable.CaseSensitive)
3040 return false;
3043 ForeignKeyConstraint constraint = null;
3044 ConstraintCollection constraints = null;
3045 for (int i = 0; i < Tables.Count; i++) {
3046 constraints = Tables[i].Constraints;
3047 for (int j = 0; j < constraints.Count; j++) {
3048 if (constraints[j] is ForeignKeyConstraint) {
3049 constraint = (ForeignKeyConstraint)constraints[j];
3050 if (constraint.Table.CaseSensitive != constraint.RelatedTable.CaseSensitive)
3051 return false;
3055 return true;
3057 finally {
3058 Bid.ScopeLeave(ref hscp);
3062 internal bool ValidateLocaleConstraint() {
3063 IntPtr hscp;
3064 Bid.ScopeEnter(out hscp, "<ds.DataSet.ValidateLocaleConstraint|INFO> %d#\n", ObjectID);
3065 try {
3066 DataRelation relation = null;
3067 for (int i = 0; i < Relations.Count; i++) {
3068 relation = Relations[i];
3069 if (relation.ChildTable.Locale.LCID != relation.ParentTable.Locale.LCID)
3070 return false;
3073 ForeignKeyConstraint constraint = null;
3074 ConstraintCollection constraints = null;
3075 for (int i = 0; i < Tables.Count; i++) {
3076 constraints = Tables[i].Constraints;
3077 for (int j = 0; j < constraints.Count; j++) {
3078 if (constraints[j] is ForeignKeyConstraint) {
3079 constraint = (ForeignKeyConstraint)constraints[j];
3080 if (constraint.Table.Locale.LCID != constraint.RelatedTable.Locale.LCID)
3081 return false;
3085 return true;
3087 finally {
3088 Bid.ScopeLeave(ref hscp);
3092 // Microsoft: may be better to rewrite this as nonrecursive?
3093 internal DataTable FindTable(DataTable baseTable, PropertyDescriptor[] props, int propStart) {
3094 if (props.Length < propStart + 1)
3095 return baseTable;
3097 PropertyDescriptor currentProp = props[propStart];
3099 if (baseTable == null) {
3100 // the accessor is the table name. if we don't find it, return null.
3101 if (currentProp is DataTablePropertyDescriptor) {
3102 return FindTable(((DataTablePropertyDescriptor)currentProp).Table, props, propStart + 1);
3104 return null;
3107 if (currentProp is DataRelationPropertyDescriptor) {
3108 return FindTable(((DataRelationPropertyDescriptor)currentProp).Relation.ChildTable, props, propStart + 1);
3111 return null;
3114 protected virtual void ReadXmlSerializable(XmlReader reader) {
3115 //WebData 96421 and 104709, this is DataSet side fix for the thrown exception
3116 // <DataSet xsi:nil="true"> does not mean DataSet is null,but it does not have any child
3117 // so dont do anything, ignore the attributes and just return empty DataSet;
3118 this.UseDataSetSchemaOnly = false;
3119 this.UdtIsWrapped = false;
3121 if (reader.HasAttributes) {
3122 const string xsinill = Keywords.XSI + ":" + Keywords.XSI_NIL;
3123 if (reader.MoveToAttribute(xsinill)) {
3124 string nilAttrib = reader.GetAttribute(xsinill);
3125 if (string.Compare(nilAttrib, "true", StringComparison.Ordinal) == 0) {// case sensitive true comparison
3126 MoveToElement(reader, 1);
3127 return;
3131 const string useDataSetSchemaOnlyString = Keywords.MSD + ":" + Keywords.USEDATASETSCHEMAONLY;
3132 if (reader.MoveToAttribute(useDataSetSchemaOnlyString)) {
3133 string _useDataSetSchemaOnly = reader.GetAttribute(useDataSetSchemaOnlyString);
3134 if (string.Equals(_useDataSetSchemaOnly, "true", StringComparison.Ordinal) ||
3135 string.Equals(_useDataSetSchemaOnly, "1", StringComparison.Ordinal))
3137 this.UseDataSetSchemaOnly = true;
3139 else if (!string.Equals(_useDataSetSchemaOnly, "false", StringComparison.Ordinal) &&
3140 !string.Equals(_useDataSetSchemaOnly, "0", StringComparison.Ordinal))
3142 throw ExceptionBuilder.InvalidAttributeValue(Keywords.USEDATASETSCHEMAONLY, _useDataSetSchemaOnly);
3146 const string udtIsWrappedString = Keywords.MSD + ":" + Keywords.UDTCOLUMNVALUEWRAPPED;
3147 if (reader.MoveToAttribute(udtIsWrappedString)) {
3148 string _udtIsWrappedString = reader.GetAttribute(udtIsWrappedString);
3149 if (string.Equals(_udtIsWrappedString, "true", StringComparison.Ordinal) ||
3150 string.Equals(_udtIsWrappedString, "1", StringComparison.Ordinal))
3152 this.UdtIsWrapped = true;
3155 else if (!string.Equals(_udtIsWrappedString, "false", StringComparison.Ordinal) &&
3156 !string.Equals(_udtIsWrappedString, "0", StringComparison.Ordinal))
3158 throw ExceptionBuilder.InvalidAttributeValue(Keywords.UDTCOLUMNVALUEWRAPPED, _udtIsWrappedString);
3162 ReadXml(reader, XmlReadMode.DiffGram, true);
3165 protected virtual System.Xml.Schema.XmlSchema GetSchemaSerializable() {
3166 return null;
3169 /************************************************************************
3170 To publish
3171 int_tools\webserviceadmin.exe -install Application Application.dll
3173 To test
3174 http://localhost/application/service.asmx?wsdl
3176 wsdl.exe /namespace:UserNamespace http://localhost/Application/Service.asmx?wsdl /out:Service.cs
3178 The V1.0 & V1.1 WSDL for Untyped DataSet being returned as a result (no parameters)
3179 <s:element name="anyUserSpecifiedMethodName">
3180 <!-- This is where parameters go -->
3181 <s:complexType />
3182 </s:element>
3183 <s:element name="anyUserSpecifiedMethodName"+"Response">
3184 <s:complexType>
3185 <s:sequence>
3186 <s:element minOccurs="0" maxOccurs="1" name="anyUserSpecifiedMethodName"+"Result">
3187 <s:complexType>
3188 <s:sequence>
3189 <s:element ref="s:schema" />
3190 <s:any />
3191 </s:sequence>
3192 </s:complexType>
3193 </s:element>
3194 </s:sequence>
3195 </s:complexType>
3196 </s:element>
3198 The V1.0 & V1.1 WSDL for Untyped DataSet as parameter, string for the result
3199 <s:element name="anyUserSpecifiedMethodName">
3200 <!-- This is where parameters go -->
3201 <s:complexType>
3202 <s:sequence>
3203 <s:element minOccurs="0" maxOccurs="1" name="set">
3204 <s:complexType>
3205 <s:sequence>
3206 <s:element ref="s:schema" />
3207 <s:any />
3208 </s:sequence>
3209 </s:complexType>
3210 </s:element>
3211 </s:sequence>
3212 </s:complexType>
3213 </s:element>
3214 <s:element name="anyUserSpecifiedMethodName"+"Response">
3215 <s:complexType>
3216 <s:sequence>
3217 <s:element minOccurs="0" maxOccurs="1" name="anyUserSpecifiedMethodName"+"Result" type="s:string" />
3218 </s:sequence>
3219 </s:complexType>
3220 </s:element>
3222 The V2.0 WSDL for Untyped DataSet being returned as a result (no parameters)
3223 <s:element name="anyUserSpecifiedMethodName">
3224 <!-- This is where parameters go -->
3225 <s:complexType />
3226 </s:element>
3227 <s:element name="anyUserSpecifiedMethodName"+"Response">
3228 <s:complexType>
3229 <s:sequence>
3230 <s:element minOccurs="0" maxOccurs="1" name="anyUserSpecifiedMethodName"+"Result">
3231 <s:complexType>
3232 <s:sequence maxOccurs="unbounded">
3233 <s:any minOccurs="0" namespace="http://www.w3.org/2001/XMLSchema" processContents="lax" />
3234 <s:any minOccurs="0" namespace="urn:schemas-microsoft-com:xml-diffgram-v1" processContents="lax" />
3235 </s:sequence>
3236 </s:complexType>
3237 </s:element>
3238 </s:sequence>
3239 </s:complexType>
3240 </s:element>
3242 The V2.0 WSDL for Untyped DataSet as a parameter, string for the result
3243 <s:element name="anyUserSpecifiedMethodName">
3244 <!-- This is where parameters go -->
3245 <s:complexType>
3246 <s:sequence>
3247 <s:element minOccurs="0" maxOccurs="1" name="anyUserSpecifiedParameterName">
3248 <s:complexType>
3249 <s:sequence maxOccurs="unbounded">
3250 <s:any minOccurs="0" namespace="http://www.w3.org/2001/XMLSchema" processContents="lax" />
3251 <s:any minOccurs="0" namespace="urn:schemas-microsoft-com:xml-diffgram-v1" processContents="lax" />
3252 </s:sequence>
3253 </s:complexType>
3254 </s:element>
3255 </s:sequence>
3256 </s:complexType>
3257 </s:element>
3258 <s:element name="anyUserSpecifiedMethodName"+"Response">
3259 <s:complexType>
3260 <s:sequence>
3261 <s:element minOccurs="0" maxOccurs="1" name="anyUserSpecifiedMethodName"+"Result" type="s:string" />
3262 </s:sequence>
3263 </s:complexType>
3264 </s:element>
3266 The V1.0, V1.1 & V2.0 WSDL for Typed DataSet
3267 <s:import schemaLocation="http://localhost/application/service.asmx?schema=typedDataSetName" namespace="typedDataSetName" />
3268 <s:element name="anyUserSpecifiedMethodName">
3269 <!-- This is where parameters go -->
3270 <s:complexType />
3271 </s:element>
3272 <s:element name="anyUserSpecifiedMethodName"+"Response">
3273 <s:complexType>
3274 <s:sequence>
3275 <s:element minOccurs="0" maxOccurs="1" name="anyUserSpecifiedMethodName"+"Result">
3276 <s:complexType>
3277 <s:sequence>
3278 <s:any namespace="typedDataSetName" />
3279 </s:sequence>
3280 </s:complexType>
3281 </s:element>
3282 </s:sequence>
3283 </s:complexType>
3284 </s:element>
3285 ************************************************************************/
3286 public static XmlSchemaComplexType GetDataSetSchema(XmlSchemaSet schemaSet) {
3287 // For performance resons we are exploiting the fact that config files content is constant
3288 // for a given appdomain so we can safely cache the prepared schema complex type and reuse it
3289 if (schemaTypeForWSDL == null) { // to change the config file, appdomain needs to restart; so it seems safe to cache the schema
3290 XmlSchemaComplexType tempWSDL = new XmlSchemaComplexType();
3291 XmlSchemaSequence sequence = new XmlSchemaSequence();
3293 if (PublishLegacyWSDL())
3294 { // Default is Version 1.0
3295 XmlSchemaElement elem = new XmlSchemaElement();
3296 elem.RefName = new XmlQualifiedName(Keywords.XSD_SCHEMA, Keywords.XSDNS);
3297 sequence.Items.Add(elem);
3298 XmlSchemaAny any = new XmlSchemaAny();
3299 sequence.Items.Add(any);
3301 else
3302 { // this means Version == V2.0 or newer
3303 XmlSchemaAny any = new XmlSchemaAny();
3304 any.Namespace = XmlSchema.Namespace;
3305 any.MinOccurs = 0;
3306 any.ProcessContents = XmlSchemaContentProcessing.Lax;
3307 sequence.Items.Add(any);
3309 any = new XmlSchemaAny();
3310 any.Namespace = Keywords.DFFNS;
3311 any.MinOccurs = 0; // when recognizing WSDL - MinOccurs="0" denotes DataSet, a MinOccurs="1" for DataTable
3312 any.ProcessContents = XmlSchemaContentProcessing.Lax;
3313 sequence.Items.Add(any);
3314 sequence.MaxOccurs = Decimal.MaxValue;
3316 tempWSDL.Particle = sequence;
3318 schemaTypeForWSDL = tempWSDL;
3320 return schemaTypeForWSDL;
3323 /********************************************
3324 <configuration>
3325 <configSections>
3326 <section name="system.data.dataset" type="System.Configuration.NameValueFileSectionHandler, System, Version=%ASSEMBLY_VERSION%, Culture=neutral, PublicKeyToken=%ECMA_PUBLICKEY%" restartOnExternalChanges="false" />
3327 </configSections>
3328 <system.data.dataset>
3329 <!-- if WSDL_VERSION is missing it will default to 1.0
3330 <add key="WSDL_VERSION" value="1.0"/>
3332 <add key="WSDL_VERSION" value="2.0"/>
3333 </system.data.dataset>
3334 </configuration>
3335 *******************************************/
3336 private static bool PublishLegacyWSDL()
3338 Single version = 1.0f; // Default is Version 1.0
3339 #if !NO_CONFIGURATION
3340 NameValueCollection settings = (NameValueCollection)PrivilegedConfigurationManager.GetSection(Keywords.WS_DATASETFULLQNAME);
3341 if (settings != null)
3343 string[] values = settings.GetValues(Keywords.WS_VERSION);
3344 if ((null != values) && (0 < values.Length) && (null != values[0]))
3345 { // will throw FormatException if not a valid number
3346 version = Single.Parse(values[0], CultureInfo.InvariantCulture);
3349 #endif
3350 return (version < 2.0f); // if config does not exist, Default is Version 1.0
3353 XmlSchema IXmlSerializable.GetSchema() {
3354 if (GetType() == typeof(DataSet)) {
3355 return null;
3357 MemoryStream stream = new MemoryStream();
3358 // WriteXmlSchema(new XmlTextWriter(stream, null));
3359 XmlWriter writer = new XmlTextWriter(stream, null);
3360 if (writer != null) {
3361 (new XmlTreeGen(SchemaFormat.WebService)).Save(this, writer);
3363 stream.Position = 0;
3364 return XmlSchema.Read(new XmlTextReader(stream), null);
3365 // return GetSchemaSerializable();
3368 void IXmlSerializable.ReadXml(XmlReader reader) {
3369 bool fNormalization = true;
3370 XmlTextReader xmlTextReader = null;
3371 IXmlTextParser xmlTextParser = reader as IXmlTextParser;
3372 if (xmlTextParser != null) {
3373 fNormalization = xmlTextParser.Normalized;
3374 xmlTextParser.Normalized = false;
3376 else {
3377 xmlTextReader = reader as XmlTextReader;
3378 if (xmlTextReader != null) {
3379 fNormalization = xmlTextReader.Normalization;
3380 xmlTextReader.Normalization = false;
3384 ReadXmlSerializable(reader);
3386 if (xmlTextParser != null)
3387 xmlTextParser.Normalized = fNormalization;
3388 else if (xmlTextReader != null)
3389 xmlTextReader.Normalization = fNormalization;
3392 void IXmlSerializable.WriteXml(XmlWriter writer) {
3393 this.WriteXmlSchema(writer, SchemaFormat.WebService, (Converter<Type, string>)null);
3394 this.WriteXml(writer, XmlWriteMode.DiffGram);
3397 public virtual void Load(IDataReader reader, LoadOption loadOption, FillErrorEventHandler errorHandler, params DataTable[] tables) {
3398 IntPtr hscp;
3399 Bid.ScopeEnter(out hscp, "<ds.DataSet.Load|API> reader, loadOption=%d{ds.LoadOption}", (int)loadOption);
3400 try {
3401 foreach (DataTable dt in tables) {
3402 Common.ADP.CheckArgumentNull(dt, "tables");
3403 if (dt.DataSet != this) {
3404 throw ExceptionBuilder.TableNotInTheDataSet(dt.TableName);
3407 Common.LoadAdapter adapter = new Common.LoadAdapter();
3408 adapter.FillLoadOption = loadOption;
3409 adapter.MissingSchemaAction = MissingSchemaAction.AddWithKey;
3410 if (null != errorHandler) {
3411 adapter.FillError += errorHandler;
3413 adapter.FillFromReader(tables, reader, 0, 0);
3415 if (!reader.IsClosed && !reader.NextResult()) { //
3416 reader.Close();
3419 finally {
3420 Bid.ScopeLeave(ref hscp);
3424 public void Load(IDataReader reader, LoadOption loadOption, params DataTable[] tables) {
3425 Load(reader, loadOption, null, tables);
3428 public void Load(IDataReader reader, LoadOption loadOption, params string[] tables) {
3429 Common.ADP.CheckArgumentNull(tables, "tables");
3430 DataTable[] dataTables = new DataTable[tables.Length];
3431 for (int i = 0; i < tables.Length; i++) {
3432 DataTable tempDT = this.Tables[tables[i]];
3433 if (null == tempDT) {
3434 tempDT = new DataTable(tables[i]);
3435 // fxcop: new DataTable should inherit the CaseSensitive, Locale, Namespace from DataSet
3436 Tables.Add(tempDT);
3438 dataTables[i] = tempDT;
3440 Load(reader, loadOption, null, dataTables);
3443 public DataTableReader CreateDataReader() {
3444 if (Tables.Count == 0)
3445 throw ExceptionBuilder.CannotCreateDataReaderOnEmptyDataSet();
3447 DataTable[] dataTables = new DataTable[Tables.Count];
3448 for (int i = 0; i < Tables.Count; i++) {
3449 dataTables[i] = Tables[i];
3451 return CreateDataReader(dataTables);
3454 public DataTableReader CreateDataReader(params DataTable[] dataTables) {
3455 IntPtr hscp;
3456 Bid.ScopeEnter(out hscp, "<ds.DataSet.GetDataReader|API> %d#\n", ObjectID);
3457 try {
3458 if (dataTables.Length == 0)
3459 throw ExceptionBuilder.DataTableReaderArgumentIsEmpty();
3461 for (int i = 0; i < dataTables.Length; i++) {
3462 if (dataTables[i] == null)
3463 throw ExceptionBuilder.ArgumentContainsNullValue();
3466 return new DataTableReader(dataTables);
3468 finally {
3469 Bid.ScopeLeave(ref hscp);
3473 internal string MainTableName {
3474 get {
3475 return mainTableName;
3477 set {
3478 this.mainTableName = value;
3482 internal int ObjectID {
3483 get {
3484 return _objectID;
3489 #endif
3491 #if !NO_CODEDOM
3492 public class DataSetSchemaImporterExtension : SchemaImporterExtension {
3493 // DataSetSchemaImporterExtension is used for WebServices, it is used to recognize the schema of DataSet within wsdl
3494 // If a non 2.0 enabled DataSetSchemaImporterExtension, wsdl will generate a classes that you can't cast to dataset / datatable
3496 Hashtable importedTypes = new Hashtable();
3498 /// <devdoc>
3499 /// <para>[To be supplied.]</para>
3500 /// </devdoc>
3501 public override string ImportSchemaType(string name, string schemaNamespace, XmlSchemaObject context, XmlSchemas schemas, XmlSchemaImporter importer, CodeCompileUnit compileUnit, CodeNamespace mainNamespace, CodeGenerationOptions options, CodeDomProvider codeProvider) {
3502 IList values = schemas.GetSchemas(schemaNamespace);
3503 if (values.Count != 1) {
3504 return null;
3506 XmlSchema schema = values[0] as XmlSchema;
3507 if (schema == null)
3508 return null;
3509 XmlSchemaType type = (XmlSchemaType)schema.SchemaTypes[new XmlQualifiedName(name, schemaNamespace)];
3510 return ImportSchemaType(type, context, schemas, importer, compileUnit, mainNamespace, options, codeProvider);
3513 /// <devdoc>
3514 /// <para>[To be supplied.]</para>
3515 /// </devdoc>
3516 public override string ImportSchemaType(XmlSchemaType type, XmlSchemaObject context, XmlSchemas schemas, XmlSchemaImporter importer, CodeCompileUnit compileUnit, CodeNamespace mainNamespace, CodeGenerationOptions options, CodeDomProvider codeProvider) {
3517 if (type == null) {
3518 return null;
3520 if (importedTypes[type] != null) {
3521 mainNamespace.Imports.Add(new CodeNamespaceImport(typeof(DataSet).Namespace));
3522 compileUnit.ReferencedAssemblies.Add("System.Data.dll");
3523 return (string)importedTypes[type];
3525 if (!(context is XmlSchemaElement))
3526 return null;
3528 XmlSchemaElement e = (XmlSchemaElement)context;
3530 // recognizing the following is important, but not as part of SQLPT 120015394: Support WSI Compliant WSDL for DataSet
3531 // <xs:element name="NewDataSet" msdata:IsDataSet="true">
3532 // see also SQLBU 338644, 410965, 423446
3533 //if (IsDataSet(e))
3535 // return GenerateTypedDataSet(e, schemas, mainNamespace, compileUnit.ReferencedAssemblies, codeProvider);
3538 if (type is XmlSchemaComplexType) {
3539 XmlSchemaComplexType ct = (XmlSchemaComplexType)type;
3541 if (ct.Particle is XmlSchemaSequence)
3543 XmlSchemaObjectCollection items = ((XmlSchemaSequence)ct.Particle).Items;
3544 if ((2 == items.Count) && (items[0] is XmlSchemaAny) && (items[1] is XmlSchemaAny))
3546 XmlSchemaAny any0 = (XmlSchemaAny)items[0];
3547 XmlSchemaAny any1 = (XmlSchemaAny)items[1];
3548 if ((any0.Namespace == XmlSchema.Namespace) && (any1.Namespace == "urn:schemas-microsoft-com:xml-diffgram-v1"))
3549 { // new diffgramm format
3550 string ns = null;
3551 foreach (XmlSchemaAttribute a in ct.Attributes)
3553 if (a.Name == "namespace")
3555 ns = a.FixedValue.Trim();
3556 break;
3559 bool isDataSet = false;
3561 // check for DataSet or DataTable
3562 if (((XmlSchemaSequence)ct.Particle).MaxOccurs == Decimal.MaxValue)
3564 isDataSet = true;
3566 else if (any0.MaxOccurs == Decimal.MaxValue)
3568 isDataSet = false;
3570 else
3572 return null;
3575 if (ns == null)
3576 { //Un-Typed DataSet / DataTable
3577 string typeName = isDataSet ? typeof(DataSet).FullName : typeof(DataTable).FullName;
3578 importedTypes.Add(type, typeName);
3579 mainNamespace.Imports.Add(new CodeNamespaceImport(typeof(DataSet).Namespace));
3580 compileUnit.ReferencedAssemblies.Add("System.Data.dll");
3581 return typeName;
3583 else
3584 { // Typed DataSet / DataTable
3585 foreach (XmlSchema schema in schemas.GetSchemas(ns))
3587 if ((schema != null) && (schema.Id != null))
3589 XmlSchemaElement ds = FindDataSetElement(schema); // implement FindDataTableElement(schema)
3590 if (ds != null)
3592 return ImportSchemaType(ds.SchemaType, ds, schemas, importer, compileUnit, mainNamespace, options, codeProvider);
3594 // else return null
3597 return null;
3602 if (ct.Particle is XmlSchemaSequence || ct.Particle is XmlSchemaAll) {
3603 XmlSchemaObjectCollection items = ((XmlSchemaGroupBase)ct.Particle).Items;
3604 if (items.Count == 2) {
3605 if (!(items[0] is XmlSchemaElement && items[1] is XmlSchemaAny)) return null;
3606 XmlSchemaElement schema = (XmlSchemaElement)items[0];
3607 if (!(schema.RefName.Name == "schema" && schema.RefName.Namespace == XmlSchema.Namespace)) return null;
3608 string typeName = typeof(DataSet).FullName;
3609 importedTypes.Add(type, typeName);
3610 mainNamespace.Imports.Add(new CodeNamespaceImport(typeof(DataSet).Namespace));
3611 compileUnit.ReferencedAssemblies.Add("System.Data.dll");
3612 return typeName;
3614 else if (1 == items.Count)
3616 XmlSchemaAny any = items[0] as XmlSchemaAny;
3617 if ((null != any) &&
3618 (null != any.Namespace) &&
3619 (any.Namespace.IndexOfAny(new char[] { '#', ' ' }) < 0)) // special syntax (##any, ##other, ...) or more than one Uri present
3621 foreach (XmlSchema schema in schemas.GetSchemas(any.Namespace))
3623 if ((null != schema) &&
3624 (null != schema.Id))
3626 XmlSchemaElement ds = FindDataSetElement(schema);
3627 if (ds != null)
3629 return ImportSchemaType(ds.SchemaType, ds, schemas, importer, compileUnit, mainNamespace, options, codeProvider);
3631 // else return null
3633 // else return null
3636 // else return null
3640 return null;
3644 internal XmlSchemaElement FindDataSetElement(XmlSchema schema) {
3645 foreach (XmlSchemaObject item in schema.Items) {
3646 if (item is XmlSchemaElement && IsDataSet((XmlSchemaElement)item)) {
3647 return (XmlSchemaElement)item;
3650 return null;
3653 internal string GenerateTypedDataSet(XmlSchemaElement element, XmlSchemas schemas, CodeNamespace codeNamespace, StringCollection references, CodeDomProvider codeProvider) {
3654 if (element == null)
3655 return null;
3657 if (importedTypes[element.SchemaType] != null)
3658 return (string)importedTypes[element.SchemaType];
3660 IList values = schemas.GetSchemas(element.QualifiedName.Namespace);
3661 if (values.Count != 1) {
3662 return null;
3664 XmlSchema schema = values[0] as XmlSchema;
3665 if (schema == null)
3666 return null;
3668 DataSet ds = new DataSet();
3671 using (MemoryStream stream = new MemoryStream()) {
3672 schema.Write(stream);
3673 stream.Position = 0;
3674 ds.ReadXmlSchema(stream);
3677 #pragma warning disable 618 // ignore obsolete warning about TypedDataSetGenerator
3678 CodeTypeDeclaration dsClass = new TypedDataSetGenerator().GenerateCode(ds, codeNamespace, codeProvider.CreateGenerator());
3679 #pragma warning restore 618
3680 string typeName = dsClass.Name;
3681 importedTypes.Add(element.SchemaType, typeName);
3682 references.Add("System.Data.dll");
3683 return typeName;
3686 internal static bool IsDataSet(XmlSchemaElement e) {
3687 if (e.UnhandledAttributes != null) {
3688 foreach (XmlAttribute a in e.UnhandledAttributes) {
3689 if (a.LocalName == "IsDataSet" && a.NamespaceURI == Keywords.MSDNS) {
3690 // currently the msdata:IsDataSet uses its own format for the boolean values
3691 if (a.Value == "True" || a.Value == "true" || a.Value == "1") return true;
3695 return false;
3698 #endif