1 //------------------------------------------------------------------------------
2 // <copyright file="DataSet.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // <owner current="true" primary="true">Microsoft</owner>
6 // <owner current="true" primary="false">Microsoft</owner>
7 //------------------------------------------------------------------------------
9 namespace System
.Data
{
12 using System
.Runtime
.Serialization
;
13 using System
.ComponentModel
;
14 using System
.Diagnostics
;
15 using System
.Globalization
;
17 using System
.Collections
;
18 using System
.Collections
.Generic
;
19 using System
.Collections
.Specialized
;
21 using System
.Xml
.Serialization
;
23 using System
.Xml
.Serialization
.Advanced
;
25 using System
.Xml
.Schema
;
26 using System
.Runtime
.Serialization
.Formatters
.Binary
; //Binary Formatter
28 using System
.CodeDom
.Compiler
;
29 using System
.Configuration
;
30 using System
.Data
.Common
;
31 using System
.Runtime
.Versioning
;
32 using System
.Runtime
.CompilerServices
;
37 /// Represents an in-memory cache of data.
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
),
46 XmlSchemaProvider("GetDataSetSchema"),
49 public class DataSet
: MarshalByValueComponent
, System
.ComponentModel
.IListSource
, IXmlSerializable
, ISupportInitializeNotification
, ISerializable
{
51 private DataViewManager defaultViewManager
;
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
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
102 /// <para>Initializes a new instance of the <see cref='System.Data.DataSet'/> class.</para>
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
114 /// <para>Initializes a new instance of a <see cref='System.Data.DataSet'/>
115 /// class with the given name.</para>
117 public DataSet(string dataSetName
)
120 this.DataSetName
= dataSetName
;
124 DefaultValue(SerializationFormat
.Xml
)
126 public SerializationFormat RemotingFormat
{
128 return _remotingFormat
;
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
146 return SchemaSerializationMode
.IncludeSchema
;
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
;
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
;
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
;
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
)
229 SerializationFormat remotingFormat
= SerializationFormat
.Xml
;
230 SchemaSerializationMode schemaSerializationMode
= SchemaSerializationMode
.IncludeSchema
;
231 SerializationInfoEnumerator e
= info
.GetEnumerator();
233 while (e
.MoveNext()) {
235 case "DataSet.RemotingFormat": //DataSet.RemotingFormat does not exist in V1/V1.1 versions
236 remotingFormat
= (SerializationFormat
)e
.Value
;
238 case "SchemaSerializationMode.DataSet": //SchemaSerializationMode.DataSet does not exist in V1/V1.1 versions
239 schemaSerializationMode
= (SchemaSerializationMode
)e
.Value
;
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() {
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
);
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());
306 for (int i
= 0; i
< Tables
.Count
; i
++) {
307 Tables
[i
].SerializeConstraints(info
, context
, i
, true);
311 SerializeRelations(info
, context
);
314 for (int i
= 0; i
< Tables
.Count
; i
++) {
315 Tables
[i
].SerializeExpressionColumns(info
, context
, i
);
319 //Serialize DataSet public properties.
320 SerializeDataSetProperties(info
, context
);
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
);
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
);
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
);
372 for (int i
= 0; i
< tableCount
; i
++) {
373 Tables
[i
].DeserializeConstraints(info
, context
, /* table index */i
, /* serialize all constraints */ true); //
377 DeserializeRelations(info
, context
);
380 for (int i
= 0; i
< tableCount
; i
++) {
381 Tables
[i
].DeserializeExpressionColumns(info
, context
, i
);
384 //DeSerialize DataSet public properties.[Locale, CaseSensitive and EnforceConstraints]
385 DeserializeDataSetProperties(info
, context
);
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
);
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
);
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");
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
);
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];
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]];
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
;
512 rel
.CheckMultipleNested
= true; // enable the check for multiple nested parent
516 internal void FailedEnableConstraints() {
517 this.EnforceConstraints
= false;
518 throw ExceptionBuilder
.EnforceConstraint();
523 /// Gets or sets a value indicating whether string
524 /// comparisons within <see cref='System.Data.DataTable'/>
530 ResCategoryAttribute(Res
.DataCategory_Data
),
532 ResDescriptionAttribute(Res
.DataSetCaseSensitiveDescr
)
534 public bool CaseSensitive
{
536 return _caseSensitive
;
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
{
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>
566 [Browsable(false), ResDescriptionAttribute(Res
.DataSetDefaultViewDescr
)]
567 public DataViewManager DefaultViewManager
{
569 if (defaultViewManager
== null) {
570 lock (_defaultViewManagerLock
) {
571 if (defaultViewManager
== null) {
572 defaultViewManager
= new DataViewManager(this, true);
576 return defaultViewManager
;
581 /// <para>Gets or sets a value indicating whether constraint rules are followed when
582 /// attempting any update operation.</para>
584 [DefaultValue(true), ResDescriptionAttribute(Res
.DataSetEnforceConstraintsDescr
)]
585 public bool EnforceConstraints
{
587 return enforceConstraints
;
591 Bid
.ScopeEnter(out hscp
, "<ds.DataSet.set_EnforceConstraints|API> %d#, %d{bool}\n", ObjectID
, value);
593 if (this.enforceConstraints
!= value) {
596 this.enforceConstraints
= value;
600 Bid
.ScopeLeave(ref hscp
);
605 internal void RestoreEnforceConstraints(bool value) {
606 this.enforceConstraints
= value;
609 internal void EnableConstraints()
612 Bid
.ScopeEnter(out hscp
, "<ds.DataSet.EnableConstraints|INFO> %d#\n", ObjectID
);
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();
632 this.FailedEnableConstraints();
635 Bid
.ScopeLeave(ref hscp
);
641 /// sets the name of this <see cref='System.Data.DataSet'/> .</para>
644 ResCategoryAttribute(Res
.DataCategory_Data
),
646 ResDescriptionAttribute(Res
.DataSetDataSetNameDescr
)
648 public string DataSetName
{
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;
670 ResCategoryAttribute(Res
.DataCategory_Data
),
671 ResDescriptionAttribute(Res
.DataSetNamespaceDescr
)
673 public string Namespace
{
678 Bid
.Trace("<ds.DataSet.set_Namespace|API> %d#, '%ls'\n", ObjectID
, value);
680 value = String
.Empty
;
681 if (value != namespaceURI
) {
682 RaisePropertyChanging("Namespace");
683 foreach (DataTable dt
in Tables
) {
684 if (dt
.tableNamespace
!= null)
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
;
705 /// <para>[To be supplied.]</para>
709 ResCategoryAttribute(Res
.DataCategory_Data
),
710 ResDescriptionAttribute(Res
.DataSetPrefixDescr
)
712 public string Prefix
{
713 get { return _datasetPrefix; }
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;
731 /// <para>Gets the collection of custom user information.</para>
734 ResCategoryAttribute(Res
.DataCategory_Data
),
736 ResDescriptionAttribute(Res
.ExtendedPropertiesDescr
)
738 public PropertyCollection ExtendedProperties
{
740 if (extendedProperties
== null) {
741 extendedProperties
= new PropertyCollection();
743 return extendedProperties
;
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'/> .
753 [Browsable(false), ResDescriptionAttribute(Res
.DataSetHasErrorsDescr
)]
754 public bool HasErrors
{
756 for (int i
= 0; i
< Tables
.Count
; i
++) {
757 if (Tables
[i
].HasErrors
)
765 public bool IsInitialized
{
767 return !fInitInProgress
;
773 /// Gets or sets the locale information used to compare strings within the table.
777 ResCategoryAttribute(Res
.DataCategory_Data
),
778 ResDescriptionAttribute(Res
.DataSetLocaleDescr
)
780 public CultureInfo Locale
{
782 // used for comparing not formating/parsing
783 Debug
.Assert(null != _culture
, "DataSet.Locale: null culture");
788 Bid
.ScopeEnter(out hscp
, "<ds.DataSet.set_Locale|API> %d#\n", ObjectID
);
791 if (!_culture
.Equals(value)) {
792 SetLocaleValue(value, true);
794 _cultureUserSet
= true;
798 Bid
.ScopeLeave(ref hscp
);
803 internal void SetLocaleValue(CultureInfo
value, bool userSet
) {
805 bool exceptionThrown
= false;
808 CultureInfo oldLocale
= _culture
;
809 bool oldUserSet
= _cultureUserSet
;
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();
825 foreach (DataTable table
in Tables
) {
827 if (!table
.ShouldSerializeLocale()) {
828 table
.SetLocaleValue(value, false, true);
835 exceptionThrown
= true;
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);
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
)) {
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
;
878 /// <para>[To be supplied.]</para>
880 [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility
.Hidden
)]
881 public override ISite Site
{
886 ISite oldSite
= Site
;
887 if (value == null && oldSite
!= null) {
888 IContainer cont
= oldSite
.Container
;
891 for (int i
= 0; i
< Tables
.Count
; i
++) {
892 if (Tables
[i
].Site
!= null) {
893 cont
.Remove(Tables
[i
]);
906 /// Get the collection of relations that link tables and
907 /// allow navigation from parent tables to child tables.
911 DesignerSerializationVisibility(DesignerSerializationVisibility
.Content
),
912 ResCategoryAttribute(Res
.DataCategory_Data
),
913 ResDescriptionAttribute(Res
.DataSetRelationsDescr
)
915 public DataRelationCollection Relations
{
917 return relationCollection
;
923 /// Indicates whether <see cref='Relations'/> property should be persisted.
926 protected virtual bool ShouldSerializeRelations() {
927 return true; /*Relations.Count > 0;*/ // VS7 300569
932 /// Resets the <see cref='System.Data.DataSet.Relations'/> property to its default state.
935 private void ResetRelations()
941 /// <para>Gets the collection of tables contained in the <see cref='System.Data.DataSet'/>.</para>
944 DesignerSerializationVisibility(DesignerSerializationVisibility
.Content
),
945 ResCategoryAttribute(Res
.DataCategory_Data
),
946 ResDescriptionAttribute(Res
.DataSetTablesDescr
)
948 public DataTableCollection Tables
{
950 return tableCollection
;
956 /// Indicates whether <see cref='System.Data.DataSet.Tables'/> property should be persisted.
959 protected virtual bool ShouldSerializeTables() {
960 return true;/*(Tables.Count > 0);*/ // VS7 300569
965 /// Resets the <see cref='System.Data.DataSet.Tables'/> property to its default state.
968 private void ResetTables()
973 internal bool FBoundToDocument
{
975 return fBoundToDocument
;
978 fBoundToDocument
= value;
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.
988 public void AcceptChanges()
991 Bid
.ScopeEnter(out hscp
, "<ds.DataSet.AcceptChanges|API> %d#\n", ObjectID
);
993 for (int i
= 0; i
< Tables
.Count
; i
++)
994 Tables
[i
].AcceptChanges();
997 Bid
.ScopeLeave(ref hscp
);
1001 internal event PropertyChangedEventHandler PropertyChanging
{
1003 onPropertyChangingDelegate
+= value;
1006 onPropertyChangingDelegate
-= value;
1011 /// <para>Occurs when attempting to merge schemas for two tables with the same
1015 ResCategoryAttribute(Res
.DataCategory_Action
),
1016 ResDescriptionAttribute(Res
.DataSetMergeFailedDescr
)
1018 public event MergeFailedEventHandler MergeFailed
{
1020 onMergeFailed
+= value;
1023 onMergeFailed
-= value;
1027 internal event DataRowCreatedEventHandler DataRowCreated
{
1029 onDataRowCreated
+= value;
1032 onDataRowCreated
-= value;
1036 internal event DataSetClearEventhandler ClearFunctionCalled
{
1038 onClearFunctionCalled
+= value;
1041 onClearFunctionCalled
-= value;
1046 ResCategoryAttribute(Res
.DataCategory_Action
),
1047 ResDescriptionAttribute(Res
.DataSetInitializedDescr
)
1049 public event System
.EventHandler Initialized
{
1051 onInitialized
+= value;
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;
1079 /// <para>Clears the <see cref='System.Data.DataSet'/> of any data by removing all rows in all tables.</para>
1084 Bid
.ScopeEnter(out hscp
, "<ds.DataSet.Clear|API> %d#\n", ObjectID
);
1086 OnClearFunctionCalled(null);
1087 bool fEnforce
= EnforceConstraints
;
1088 EnforceConstraints
= false;
1089 for (int i
= 0; i
< Tables
.Count
; i
++)
1091 EnforceConstraints
= fEnforce
;
1094 Bid
.ScopeLeave(ref hscp
);
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>
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() {
1106 Bid
.ScopeEnter(out hscp
, "<ds.DataSet.Clone|API> %d#\n", ObjectID
);
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.
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
;
1121 ds
.RemotingFormat
= RemotingFormat
;
1122 ds
.fIsSchemaLoading
= true; //delay expression evaluation
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.
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
)
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
));
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
1177 Bid
.ScopeLeave(ref hscp
);
1182 /// <para>Copies both the structure and data for this <see cref='System.Data.DataSet'/>.</para>
1184 public DataSet
Copy()
1187 Bid
.ScopeEnter(out hscp
, "<ds.DataSet.Copy|API> %d#\n", ObjectID
);
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
;
1205 Bid
.ScopeLeave(ref hscp
);
1209 internal Int32
EstimatedXmlStringSize()
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);
1219 bytes
+= table
.Rows
.Count
* rowBytes
;
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>
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
);
1243 internal int HasChanges
{
1244 get { return _hasChanges; }
1245 set { _hasChanges = value; }
1247 internal bool this[int index
] {
1248 get { return _rowChanges[index]; }
1250 Debug
.Assert(value && !_rowChanges
[index
], "setting twice or to false");
1251 _rowChanges
[index
] = value;
1257 public DataSet
GetChanges(DataRowState rowStates
)
1260 Bid
.ScopeEnter(out hscp
, "<ds.DataSet.GetChanges|API> %d#, rowStates=%d{ds.DataRowState}\n", ObjectID
, (int)rowStates
);
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
;
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()
1379 Bid
.ScopeEnter(out hscp
, "<ds.DataSet.GetXml|API> %d#\n", ObjectID
);
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();
1393 Bid
.ScopeLeave(ref hscp
);
1397 public string GetXmlSchema()
1400 Bid
.ScopeEnter(out hscp
, "<ds.DataSet.GetXmlSchema|API> %d#\n", ObjectID
);
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();
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
);
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();
1438 /// <para>Gets a value indicating whether the <see cref='System.Data.DataSet'/> has changes, including new,
1439 /// deleted, or modified rows.</para>
1441 public bool HasChanges()
1443 return HasChanges(DataRowState
.Added
| DataRowState
.Deleted
| DataRowState
.Modified
);
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>
1450 public bool HasChanges(DataRowState rowStates
)
1453 Bid
.ScopeEnter(out hscp
, "<ds.DataSet.HasChanges|API> %d#, rowStates=%d{ds.DataRowState}\n", ObjectID
, (int)rowStates
);
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) {
1475 Bid
.ScopeLeave(ref hscp
);
1480 /// <para>Infer the XML schema from the specified <see cref='System.IO.TextReader'/> into the <see cref='System.Data.DataSet'/>.</para>
1482 public void InferXmlSchema(XmlReader reader
, string[] nsArray
)
1485 Bid
.ScopeEnter(out hscp
, "<ds.DataSet.InferXmlSchema|API> %d#\n", ObjectID
);
1490 XmlDocument xdoc
= new XmlDocument();
1491 if (reader
.NodeType
== XmlNodeType
.Element
) {
1492 XmlNode node
= xdoc
.ReadNode(reader
);
1493 xdoc
.AppendChild(node
);
1497 if (xdoc
.DocumentElement
== null)
1500 InferSchema(xdoc
, nsArray
, XmlReadMode
.InferSchema
);
1503 Bid
.ScopeLeave(ref hscp
);
1508 /// <para>Infer the XML schema from the specified <see cref='System.IO.TextReader'/> into the <see cref='System.Data.DataSet'/>.</para>
1510 public void InferXmlSchema(Stream stream
, string[] nsArray
)
1515 InferXmlSchema(new XmlTextReader(stream
), nsArray
);
1519 /// <para>Infer the XML schema from the specified <see cref='System.IO.TextReader'/> into the <see cref='System.Data.DataSet'/>.</para>
1521 public void InferXmlSchema(TextReader reader
, string[] nsArray
)
1526 InferXmlSchema(new XmlTextReader(reader
), nsArray
);
1530 /// <para>Infer the XML schema from the specified file into the <see cref='System.Data.DataSet'/>.</para>
1532 [ResourceExposure(ResourceScope
.Machine
)]
1533 [ResourceConsumption(ResourceScope
.Machine
)]
1534 public void InferXmlSchema(String fileName
, string[] nsArray
)
1536 XmlTextReader xr
= new XmlTextReader(fileName
);
1538 InferXmlSchema(xr
, nsArray
);
1546 /// <para>Reads the XML schema from the specified <see cref='T:System.Xml.XMLReader'/> into the <see cref='System.Data.DataSet'/>
1549 public void ReadXmlSchema(XmlReader reader
)
1551 ReadXmlSchema(reader
, false);
1554 internal void ReadXmlSchema(XmlReader reader
, bool denyResolving
)
1557 Bid
.ScopeEnter(out hscp
, "<ds.DataSet.ReadXmlSchema|INFO> %d#, reader, denyResolving=%d{bool}\n", ObjectID
, denyResolving
);
1559 int iCurrentDepth
= -1;
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
);
1583 if (reader
.LocalName
== Keywords
.XSD_SCHEMA
&& reader
.NamespaceURI
== Keywords
.XSDNS
) {
1584 // load XSD schema and exit
1585 ReadXSDSchema(reader
, denyResolving
);
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
));
1601 XmlAttribute attr
= topNode
.SetAttributeNode(reader
.LocalName
, reader
.NamespaceURI
);
1602 attr
.Prefix
= reader
.Prefix
;
1603 attr
.Value
= reader
.GetAttribute(i
);
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
);
1618 if (reader
.LocalName
== Keywords
.XSD_SCHEMA
&& reader
.NamespaceURI
== Keywords
.XSDNS
) {
1619 // load XSD schema and exit
1620 ReadXSDSchema(reader
, denyResolving
);
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
);
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
) {
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
) {
1660 internal void ReadEndElement(XmlReader reader
) {
1661 while (reader
.NodeType
== XmlNodeType
.Whitespace
) {
1664 if (reader
.NodeType
== XmlNodeType
.None
) {
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);
1690 ReadEndElement(reader
);
1692 if (--schemaFragmentCount
> 0) {
1693 MoveToElement(reader
);
1695 while (reader
.NodeType
== XmlNodeType
.Whitespace
) {
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);
1714 /// <para>Reads the XML schema from the specified <see cref='System.IO.Stream'/> into the
1715 /// <see cref='System.Data.DataSet'/>.</para>
1717 public void ReadXmlSchema(Stream stream
)
1722 ReadXmlSchema(new XmlTextReader(stream
), false);
1726 /// <para>Reads the XML schema from the specified <see cref='System.IO.TextReader'/> into the <see cref='System.Data.DataSet'/>.</para>
1728 public void ReadXmlSchema(TextReader reader
)
1733 ReadXmlSchema(new XmlTextReader(reader
), false);
1737 /// <para>Reads the XML schema from the specified file into the <see cref='System.Data.DataSet'/>.</para>
1739 [ResourceExposure(ResourceScope
.Machine
)]
1740 [ResourceConsumption(ResourceScope
.Machine
)]
1741 public void ReadXmlSchema(String fileName
)
1743 XmlTextReader xr
= new XmlTextReader(fileName
);
1745 ReadXmlSchema(xr
, false);
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 );
1827 xw
.Formatting
= Formatting
.Indented
;
1828 xw
.WriteStartDocument(true);
1829 this.WriteXmlSchema(xw
, schemaFormat
, multipleTargetConverter
);
1830 xw
.WriteEndDocument();
1837 private void WriteXmlSchema(Stream stream
, SchemaFormat schemaFormat
, Converter
<Type
, string> multipleTargetConverter
)
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
)
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
)
1862 Bid
.ScopeEnter(out hscp
, "<ds.DataSet.WriteXmlSchema|INFO> %d#, schemaFormat=%d{ds.SchemaFormat}\n", ObjectID
, (int)schemaFormat
);
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
);
1873 treeGen
= new XmlTreeGen(schemaFormat
);
1876 treeGen
.Save(this, (DataTable
)null, writer
, false, multipleTargetConverter
);
1880 Bid
.ScopeLeave(ref hscp
);
1887 public XmlReadMode
ReadXml(XmlReader reader
)
1889 return ReadXml(reader
, false);
1893 internal XmlReadMode
ReadXml(XmlReader reader
, bool denyResolving
)
1896 Bid
.ScopeEnter(out hscp
, "<ds.DataSet.ReadXml|INFO> %d#, denyResolving=%d{bool}\n", ObjectID
, denyResolving
);
1899 DataTable
.DSRowDiffIdUsageSection rowDiffIdUsage
= new DataTable
.DSRowDiffIdUsageSection();
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);
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
));
1968 XmlAttribute attr
= topNode
.SetAttributeNode(reader
.LocalName
, reader
.NamespaceURI
);
1969 attr
.Prefix
= reader
.Prefix
;
1970 attr
.Value
= reader
.GetAttribute(i
);
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;
1998 if (reader
.LocalName
== Keywords
.XSD_SCHEMA
&& reader
.NamespaceURI
== Keywords
.XSDNS
) {
1999 // load XSD schema and exit
2000 ReadXSDSchema(reader
, denyResolving
);
2001 fSchemaFound
= true;
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
);
2011 ret
= XmlReadMode
.DiffGram
;
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
)
2019 if (reader
.NodeType
!= XmlNodeType
.Element
)
2021 // we found data here
2024 if (!fSchemaFound
&& Tables
.Count
== 0) {
2025 XmlNode node
= xdoc
.ReadNode(reader
);
2026 topNode
.AppendChild(node
);
2029 if (xmlload
== null)
2030 xmlload
= new XmlDataLoader(this, fIsXdr
, topNode
, false);
2031 xmlload
.LoadData(reader
);
2032 topNodeIsProcessed
= true; // we process the topnode
2034 ret
= XmlReadMode
.ReadSchema
;
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;
2079 xmlload
.LoadData(xdoc
);
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
2090 if (!fSchemaFound
&& Tables
.Count
== 0) {
2091 InferSchema(xdoc
, null, XmlReadMode
.Auto
);
2092 ret
= XmlReadMode
.InferSchema
;
2093 xmlload
.FromInference
= true;
2095 xmlload
.LoadData(xdoc
);
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
;
2110 rowDiffIdUsage
.Cleanup();
2114 Bid
.ScopeLeave(ref hscp
);
2121 public XmlReadMode
ReadXml(Stream stream
)
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);
2136 public XmlReadMode
ReadXml(TextReader reader
)
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);
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);
2169 internal void InferSchema(XmlDocument xdoc
, string[] excludedNamespaces
, XmlReadMode mode
) {
2171 Bid
.ScopeEnter(out hscp
, "<ds.DataSet.InferSchema|INFO> %d#, mode=%d{ds.XmlReadMode}\n", ObjectID
, (int)mode
);
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
;
2185 infer
.TypeInference
= XmlSchemaInference
.InferenceOption
.Relaxed
;
2187 XmlSchemaSet schemaSet
= infer
.InferSchema(xnr
);
2188 schemaSet
.Compile();
2190 XSDSchema schema
= new XSDSchema();
2191 schema
.FromInference
= true;
2194 schema
.LoadSchema(schemaSet
, this);
2197 schema
.FromInference
= false; // this is always false if you are not calling fron inference
2201 Bid
.ScopeLeave(ref hscp
);
2205 private bool IsEmpty() {
2206 foreach (DataTable table
in this.Tables
)
2207 if (table
.Rows
.Count
> 0)
2212 private void ReadXmlDiffgram(XmlReader reader
) {
2214 Bid
.ScopeEnter(out hscp
, "<ds.DataSet.ReadXmlDiffgram|INFO> %d#\n", ObjectID
);
2216 int d
= reader
.Depth
;
2217 bool fEnforce
= this.EnforceConstraints
;
2218 this.EnforceConstraints
= false;
2220 bool isEmpty
= this.IsEmpty();
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
))
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
);
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
) {
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
);
2303 if (this.dataSetName
== "NewDataSet")
2304 this.dataSetName
= newDs
.dataSetName
;
2305 newDs
.EnforceConstraints
= fEnforce
;
2307 this.EnforceConstraints
= fEnforce
;
2310 Bid
.ScopeLeave(ref hscp
);
2317 public XmlReadMode
ReadXml(XmlReader reader
, XmlReadMode mode
)
2319 return ReadXml(reader
, mode
, false);
2322 internal XmlReadMode
ReadXml(XmlReader reader
, XmlReadMode mode
, bool denyResolving
)
2325 Bid
.ScopeEnter(out hscp
, "<ds.DataSet.ReadXml|INFO> %d#, mode=%d{ds.XmlReadMode}, denyResolving=%d{bool}\n", ObjectID
, (int)mode
, denyResolving
);
2328 XmlReadMode ret
= mode
;
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();
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
);
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
);
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
);
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
));
2417 XmlAttribute attr
= topNode
.SetAttributeNode(reader
.LocalName
, reader
.NamespaceURI
);
2418 attr
.Prefix
= reader
.Prefix
;
2419 attr
.Value
= reader
.GetAttribute(i
);
2426 while (MoveToElement(reader
, iCurrentDepth
)) {
2428 if (reader
.LocalName
== Keywords
.XDR_SCHEMA
&& reader
.NamespaceURI
== Keywords
.XDRNS
) {
2430 if (!fSchemaFound
&& !fDataFound
&& (mode
!= XmlReadMode
.IgnoreSchema
) && (mode
!= XmlReadMode
.InferSchema
) &&
2431 (mode
!= XmlReadMode
.InferTypedSchema
))
2433 ReadXDRSchema(reader
);
2434 fSchemaFound
= true;
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;
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
;
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
) {
2473 continue; // we do not read data in diffgram mode
2476 // if we are here we found some data
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
);
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
2504 if (mode
== XmlReadMode
.InferSchema
|| mode
== XmlReadMode
.InferTypedSchema
) {
2505 InferSchema(xdoc
, null, mode
);
2506 ret
= XmlReadMode
.InferSchema
;
2507 xmlload
.FromInference
= true;
2510 xmlload
.LoadData(xdoc
);
2513 xmlload
.FromInference
= false;
2521 // Dev11 904428: prepare and cleanup rowDiffId hashtable
2522 rowDiffIdUsage
.Cleanup();
2526 Bid
.ScopeLeave(ref hscp
);
2533 public XmlReadMode
ReadXml(Stream stream
, XmlReadMode mode
)
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);
2546 public XmlReadMode
ReadXml(TextReader reader
, XmlReadMode mode
)
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);
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);
2569 xr
= new XmlTextReader(fileName
);
2571 // Prevent Dtd entity in dataset
2572 xr
.XmlResolver
= null;
2576 return ReadXml(xr
, mode
, false);
2585 /// Writes schema and data for the DataSet.
2587 public void WriteXml(Stream stream
)
2589 WriteXml(stream
, XmlWriteMode
.IgnoreSchema
);
2594 public void WriteXml(TextWriter writer
)
2596 WriteXml(writer
, XmlWriteMode
.IgnoreSchema
);
2601 public void WriteXml(XmlWriter writer
)
2603 WriteXml(writer
, XmlWriteMode
.IgnoreSchema
);
2607 /// <para>[To be supplied.]</para>
2609 [ResourceExposure(ResourceScope
.Machine
)]
2610 [ResourceConsumption(ResourceScope
.Machine
)]
2611 public void WriteXml(String fileName
)
2613 WriteXml(fileName
, XmlWriteMode
.IgnoreSchema
);
2617 /// Writes schema and data for the DataSet.
2619 public void WriteXml(Stream stream
, XmlWriteMode mode
)
2621 if (stream
!= null) {
2622 XmlTextWriter w
= new XmlTextWriter(stream
, null);
2623 w
.Formatting
= Formatting
.Indented
;
2631 public void WriteXml(TextWriter writer
, XmlWriteMode mode
)
2633 if (writer
!= null) {
2634 XmlTextWriter w
= new XmlTextWriter(writer
);
2635 w
.Formatting
= Formatting
.Indented
;
2643 public void WriteXml(XmlWriter writer
, XmlWriteMode mode
)
2646 Bid
.ScopeEnter(out hscp
, "<ds.DataSet.WriteXml|API> %d#, mode=%d{ds.XmlWriteMode}\n", ObjectID
, (int)mode
);
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
);
2657 // Create and save xml data
2658 new XmlDataTreeWriter(this).Save(writer
, mode
== XmlWriteMode
.WriteSchema
);
2663 Bid
.ScopeLeave(ref hscp
);
2668 /// <para>[To be supplied.]</para>
2670 [ResourceExposure(ResourceScope
.Machine
)]
2671 [ResourceConsumption(ResourceScope
.Machine
)]
2672 public void WriteXml(String fileName
, XmlWriteMode mode
)
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);
2678 xw
.Formatting
= Formatting
.Indented
;
2679 xw
.WriteStartDocument(true);
2681 // Create and save the updates
2682 if (mode
== XmlWriteMode
.DiffGram
) {
2683 new NewDiffgramGen(this).Save(xw
);
2686 // Create and save xml data
2687 new XmlDataTreeWriter(this).Save(xw
, mode
== XmlWriteMode
.WriteSchema
);
2690 xw
.WriteEndDocument();
2694 Bid
.ScopeLeave(ref hscp
);
2700 /// Gets the collection of parent relations which belong to a
2701 /// specified table.
2704 internal DataRelationCollection
GetParentRelations(DataTable table
)
2706 return table
.ParentRelations
;
2711 /// Merges this <see cref='System.Data.DataSet'/> into a specified <see cref='System.Data.DataSet'/>.
2714 public void Merge(DataSet dataSet
)
2717 Bid
.ScopeEnter(out hscp
, "<ds.DataSet.Merge|API> %d#, dataSet=%d\n", ObjectID
, (dataSet
!= null) ? dataSet
.ObjectID
: 0);
2719 Merge(dataSet
, false, MissingSchemaAction
.Add
);
2722 Bid
.ScopeLeave(ref hscp
);
2728 /// Merges this <see cref='System.Data.DataSet'/> into a specified <see cref='System.Data.DataSet'/> preserving changes according to
2729 /// the specified argument.
2732 public void Merge(DataSet dataSet
, bool preserveChanges
)
2735 Bid
.ScopeEnter(out hscp
, "<ds.DataSet.Merge|API> %d#, dataSet=%d, preserveChanges=%d{bool}\n", ObjectID
, (dataSet
!= null) ? dataSet
.ObjectID
: 0, preserveChanges
);
2737 Merge(dataSet
, preserveChanges
, MissingSchemaAction
.Add
);
2740 Bid
.ScopeLeave(ref hscp
);
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.
2751 public void Merge(DataSet dataSet
, bool preserveChanges
, MissingSchemaAction missingSchemaAction
) {
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
);
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
);
2769 throw Common
.ADP
.InvalidMissingSchemaAction(missingSchemaAction
);
2773 Bid
.ScopeLeave(ref hscp
);
2779 /// Merges this <see cref='System.Data.DataTable'/> into a specified <see cref='System.Data.DataTable'/>.
2782 public void Merge(DataTable table
)
2785 Bid
.ScopeEnter(out hscp
, "<ds.DataSet.Merge|API> %d#, table=%d\n", ObjectID
, (table
!= null) ? table
.ObjectID
: 0);
2787 Merge(table
, false, MissingSchemaAction
.Add
);
2790 Bid
.ScopeLeave(ref hscp
);
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.
2800 public void Merge(DataTable table
, bool preserveChanges
, MissingSchemaAction missingSchemaAction
)
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
);
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
);
2818 throw Common
.ADP
.InvalidMissingSchemaAction(missingSchemaAction
);
2822 Bid
.ScopeLeave(ref hscp
);
2828 /// <para>[To be supplied.]</para>
2830 public void Merge(DataRow
[] rows
)
2833 Bid
.ScopeEnter(out hscp
, "<ds.DataSet.Merge|API> %d#, rows\n", ObjectID
);
2835 Merge(rows
, false, MissingSchemaAction
.Add
);
2838 Bid
.ScopeLeave(ref hscp
);
2843 /// <para>[To be supplied.]</para>
2845 public void Merge(DataRow
[] rows
, bool preserveChanges
, MissingSchemaAction missingSchemaAction
)
2848 Bid
.ScopeEnter(out hscp
, "<ds.DataSet.Merge|API> %d#, preserveChanges=%d{bool}, missingSchemaAction=%d{ds.MissingSchemaAction}\n", ObjectID
, preserveChanges
, (int)missingSchemaAction
);
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
);
2863 throw Common
.ADP
.InvalidMissingSchemaAction(missingSchemaAction
);
2867 Bid
.ScopeLeave(ref hscp
);
2871 protected virtual void OnPropertyChanging(PropertyChangedEventArgs pcevent
)
2873 if (onPropertyChangingDelegate
!= null)
2874 onPropertyChangingDelegate(this, pcevent
);
2878 /// Inheriting classes should override this method to handle this event.
2879 /// Call base.OnMergeFailed to send this event to any registered event
2882 internal void OnMergeFailed(MergeFailedEventArgs mfevent
)
2884 if (onMergeFailed
!= null)
2885 onMergeFailed(this, mfevent
);
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
);
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
);
2917 /// This method should be overriden by subclasses to restrict tables being removed.
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
);
2930 /// This method should be overriden by subclasses to restrict tables being removed.
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
>();
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)
2976 return topTables
.ToArray();
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.
2985 public virtual void RejectChanges()
2988 Bid
.ScopeEnter(out hscp
, "<ds.DataSet.RejectChanges|API> %d#\n", ObjectID
);
2990 bool fEnforce
= EnforceConstraints
;
2991 EnforceConstraints
= false;
2992 for (int i
= 0; i
< Tables
.Count
; i
++)
2993 Tables
[i
].RejectChanges();
2994 EnforceConstraints
= fEnforce
;
2997 Bid
.ScopeLeave(ref hscp
);
3002 /// Resets the dataSet back to it's original state. Subclasses should override
3003 /// to restore back to it's original state.
3006 public virtual void Reset()
3009 Bid
.ScopeEnter(out hscp
, "<ds.DataSet.Reset|API> %d#\n", ObjectID
);
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
]);
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
3028 Bid
.ScopeLeave(ref hscp
);
3032 internal bool ValidateCaseConstraint() {
3034 Bid
.ScopeEnter(out hscp
, "<ds.DataSet.ValidateCaseConstraint|INFO> %d#\n", ObjectID
);
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
)
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
)
3058 Bid
.ScopeLeave(ref hscp
);
3062 internal bool ValidateLocaleConstraint() {
3064 Bid
.ScopeEnter(out hscp
, "<ds.DataSet.ValidateLocaleConstraint|INFO> %d#\n", ObjectID
);
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
)
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
)
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)
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);
3107 if (currentProp
is DataRelationPropertyDescriptor
) {
3108 return FindTable(((DataRelationPropertyDescriptor
)currentProp
).Relation
.ChildTable
, props
, propStart
+ 1);
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);
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() {
3169 /************************************************************************
3171 int_tools\webserviceadmin.exe -install Application Application.dll
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 -->
3183 <s:element name="anyUserSpecifiedMethodName"+"Response">
3186 <s:element minOccurs="0" maxOccurs="1" name="anyUserSpecifiedMethodName"+"Result">
3189 <s:element ref="s:schema" />
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 -->
3203 <s:element minOccurs="0" maxOccurs="1" name="set">
3206 <s:element ref="s:schema" />
3214 <s:element name="anyUserSpecifiedMethodName"+"Response">
3217 <s:element minOccurs="0" maxOccurs="1" name="anyUserSpecifiedMethodName"+"Result" type="s:string" />
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 -->
3227 <s:element name="anyUserSpecifiedMethodName"+"Response">
3230 <s:element minOccurs="0" maxOccurs="1" name="anyUserSpecifiedMethodName"+"Result">
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" />
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 -->
3247 <s:element minOccurs="0" maxOccurs="1" name="anyUserSpecifiedParameterName">
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" />
3258 <s:element name="anyUserSpecifiedMethodName"+"Response">
3261 <s:element minOccurs="0" maxOccurs="1" name="anyUserSpecifiedMethodName"+"Result" type="s:string" />
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 -->
3272 <s:element name="anyUserSpecifiedMethodName"+"Response">
3275 <s:element minOccurs="0" maxOccurs="1" name="anyUserSpecifiedMethodName"+"Result">
3278 <s:any namespace="typedDataSetName" />
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
);
3302 { // this means Version == V2.0 or newer
3303 XmlSchemaAny any
= new XmlSchemaAny();
3304 any
.Namespace
= XmlSchema
.Namespace
;
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 /********************************************
3326 <section name="system.data.dataset" type="System.Configuration.NameValueFileSectionHandler, System, Version=%ASSEMBLY_VERSION%, Culture=neutral, PublicKeyToken=%ECMA_PUBLICKEY%" restartOnExternalChanges="false" />
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>
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
);
3350 return (version
< 2.0f
); // if config does not exist, Default is Version 1.0
3353 XmlSchema IXmlSerializable
.GetSchema() {
3354 if (GetType() == typeof(DataSet
)) {
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;
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
) {
3399 Bid
.ScopeEnter(out hscp
, "<ds.DataSet.Load|API> reader, loadOption=%d{ds.LoadOption}", (int)loadOption
);
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()) { //
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
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
) {
3456 Bid
.ScopeEnter(out hscp
, "<ds.DataSet.GetDataReader|API> %d#\n", ObjectID
);
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
);
3469 Bid
.ScopeLeave(ref hscp
);
3473 internal string MainTableName
{
3475 return mainTableName
;
3478 this.mainTableName
= value;
3482 internal int ObjectID
{
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();
3499 /// <para>[To be supplied.]</para>
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) {
3506 XmlSchema schema
= values
[0] as XmlSchema
;
3509 XmlSchemaType type
= (XmlSchemaType
)schema
.SchemaTypes
[new XmlQualifiedName(name
, schemaNamespace
)];
3510 return ImportSchemaType(type
, context
, schemas
, importer
, compileUnit
, mainNamespace
, options
, codeProvider
);
3514 /// <para>[To be supplied.]</para>
3516 public override string ImportSchemaType(XmlSchemaType type
, XmlSchemaObject context
, XmlSchemas schemas
, XmlSchemaImporter importer
, CodeCompileUnit compileUnit
, CodeNamespace mainNamespace
, CodeGenerationOptions options
, CodeDomProvider codeProvider
) {
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
))
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
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
3551 foreach (XmlSchemaAttribute a
in ct
.Attributes
)
3553 if (a
.Name
== "namespace")
3555 ns
= a
.FixedValue
.Trim();
3559 bool isDataSet
= false;
3561 // check for DataSet or DataTable
3562 if (((XmlSchemaSequence
)ct
.Particle
).MaxOccurs
== Decimal
.MaxValue
)
3566 else if (any0
.MaxOccurs
== Decimal
.MaxValue
)
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");
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)
3592 return ImportSchemaType(ds
.SchemaType
, ds
, schemas
, importer
, compileUnit
, mainNamespace
, options
, codeProvider
);
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");
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
);
3629 return ImportSchemaType(ds
.SchemaType
, ds
, schemas
, importer
, compileUnit
, mainNamespace
, options
, codeProvider
);
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
;
3653 internal string GenerateTypedDataSet(XmlSchemaElement element
, XmlSchemas schemas
, CodeNamespace codeNamespace
, StringCollection references
, CodeDomProvider codeProvider
) {
3654 if (element
== 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) {
3664 XmlSchema schema
= values
[0] as XmlSchema
;
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");
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;