xmlsaver.cs 132 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036
  1. //------------------------------------------------------------------------------
  2. // <copyright file="xmlsaver.cs" company="Microsoft">
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  4. // </copyright>
  5. // <owner current="true" primary="true">[....]</owner>
  6. // <owner current="true" primary="false">[....]</owner>
  7. //------------------------------------------------------------------------------
  8. namespace System.Data {
  9. using System;
  10. using System.Collections;
  11. using System.ComponentModel;
  12. using System.Data.SqlTypes;
  13. using System.Data.Common;
  14. using System.Diagnostics;
  15. using System.Globalization;
  16. using System.IO;
  17. using System.Text;
  18. using System.Xml;
  19. using System.Xml.Serialization;
  20. using System.Runtime.Versioning;
  21. internal enum SchemaFormat {
  22. Public = 1,
  23. Remoting = 2,
  24. WebService = 3,
  25. RemotingSkipSchema = 4,
  26. WebServiceSkipSchema = 5
  27. }
  28. /// <devdoc>
  29. /// </devdoc>
  30. internal sealed class XmlTreeGen {
  31. ArrayList ConstraintNames;
  32. Hashtable namespaces;
  33. Hashtable autogenerated;
  34. Hashtable prefixes;
  35. DataSet _ds;
  36. ArrayList _tables = new ArrayList();
  37. ArrayList _relations = new ArrayList();
  38. XmlDocument _dc;
  39. XmlElement _sRoot;
  40. int prefixCount = 0;
  41. private SchemaFormat schFormat = SchemaFormat.Public;
  42. private string filePath = null;
  43. private string fileName = null;
  44. private string fileExt = null;
  45. XmlElement dsElement = null;
  46. XmlElement constraintSeparator = null;
  47. /// <summary>
  48. /// This converter allows new versions of the framework to write
  49. /// the assembly version of older versions of the framework.
  50. /// For example, having Dev10 using V4.0 target V2.0 of the framework.
  51. /// </summary>
  52. Converter<Type, string> targetConverter;
  53. internal XmlTreeGen(SchemaFormat format) {
  54. this.schFormat = format;
  55. }
  56. internal static void AddExtendedProperties(PropertyCollection props, XmlElement node) {
  57. AddExtendedProperties(props, node, null);
  58. }
  59. internal static void AddExtendedProperties(PropertyCollection props, XmlElement node, Type type) {
  60. if(props != null) {
  61. foreach(DictionaryEntry entry in props) {
  62. String s, v;
  63. if (entry.Key is INullable) {
  64. s = (String) SqlConvert.ChangeTypeForXML(entry.Key, typeof(string));
  65. }
  66. else {
  67. s = (String) Convert.ToString(entry.Key, CultureInfo.InvariantCulture);
  68. }
  69. if (entry.Value is INullable) {
  70. v = (String) SqlConvert.ChangeTypeForXML(entry.Value, typeof(string));
  71. }
  72. else if (entry.Value is System.Numerics.BigInteger) {
  73. v = (string)BigIntegerStorage.ConvertFromBigInteger((System.Numerics.BigInteger)entry.Value, typeof(string), CultureInfo.InvariantCulture);
  74. }
  75. else {
  76. v = (String) Convert.ToString(entry.Value, CultureInfo.InvariantCulture);
  77. }
  78. if (type == typeof(DataRelation)) {
  79. s = Keywords.MSD_REL_PREFIX + s;
  80. }
  81. else if (type == typeof(ForeignKeyConstraint)) {
  82. s = Keywords.MSD_FK_PREFIX + s;
  83. }
  84. node.SetAttribute(XmlConvert.EncodeLocalName(s), Keywords.MSPROPNS, v);
  85. }
  86. }
  87. }
  88. internal void AddXdoProperties(Object instance, XmlElement root, XmlDocument xd) {
  89. if (instance == null) {
  90. return;
  91. }
  92. PropertyDescriptorCollection pds = TypeDescriptor.GetProperties(instance) ;
  93. if (!((instance is DataSet) || (instance is DataTable) || (instance is DataColumn) || (instance is DataRelation))) {
  94. return;
  95. }
  96. for (int i = 0 ; i < pds.Count ; i++) {
  97. AddXdoProperty(pds[i], instance, root, xd);
  98. }
  99. return;
  100. }
  101. internal void AddXdoProperty(PropertyDescriptor pd, Object instance, XmlElement root, XmlDocument xd) {
  102. Type type = pd.PropertyType;
  103. bool bisDataColumn = false;
  104. DataColumn col = null; // it may cause problem to assign null here, I will need to change this.
  105. bool bIsSqlType = false;
  106. bool bImplementsInullable = false;
  107. if (instance is DataColumn) {
  108. col = (DataColumn)instance;
  109. bisDataColumn = true;
  110. bIsSqlType = col.IsSqlType;
  111. bImplementsInullable = col.ImplementsINullable;
  112. }
  113. if (bImplementsInullable == false &&
  114. type != typeof(string) && // DO NOT REMOVE THIS
  115. type != typeof(bool) &&
  116. type != typeof(Type) &&
  117. type != typeof(object) &&
  118. type != typeof(CultureInfo) &&
  119. type != typeof(Int64) &&
  120. type != typeof(Int32) ) {
  121. return;
  122. }
  123. if ((!pd.ShouldSerializeValue(instance) || !pd.Attributes.Contains(DesignerSerializationVisibilityAttribute.Visible))&&( bIsSqlType == false)) {
  124. return;
  125. }
  126. Object propInst = pd.GetValue(instance) ;
  127. if (propInst is InternalDataCollectionBase)
  128. return;
  129. if (propInst is PropertyCollection) {
  130. return;
  131. }
  132. // [....]: perf: Why not have this as a table?
  133. // there are several xdo properties that equal to some xml attributes, we should not explicitly ouput them.
  134. if (
  135. 0 == String.Compare(pd.Name, "Namespace" , StringComparison.Ordinal) ||
  136. 0 == String.Compare(pd.Name, "PrimaryKey" , StringComparison.Ordinal) ||
  137. 0 == String.Compare(pd.Name, "ColumnName" , StringComparison.Ordinal) ||
  138. 0 == String.Compare(pd.Name, "DefaultValue" , StringComparison.Ordinal) ||
  139. 0 == String.Compare(pd.Name, "TableName" , StringComparison.Ordinal) ||
  140. 0 == String.Compare(pd.Name, "DataSetName" , StringComparison.Ordinal) ||
  141. 0 == String.Compare(pd.Name, "AllowDBNull" , StringComparison.Ordinal) ||
  142. 0 == String.Compare(pd.Name, "Unique" , StringComparison.Ordinal) ||
  143. 0 == String.Compare(pd.Name, "NestedInDataSet" , StringComparison.Ordinal) ||
  144. 0 == String.Compare(pd.Name, "Locale" , StringComparison.Ordinal) ||
  145. 0 == String.Compare(pd.Name, "CaseSensitive", StringComparison.Ordinal) ||
  146. 0 == String.Compare(pd.Name, "RemotingFormat" , StringComparison.Ordinal)
  147. ) {
  148. return;
  149. }
  150. if (bisDataColumn){ //(instance is DataColumn) {
  151. if (0 == String.Compare(pd.Name, "DataType", StringComparison.Ordinal)) {
  152. string dt = XmlDataTypeName(col.DataType);
  153. if(bIsSqlType || (col.DataType == typeof(System.Numerics.BigInteger))) {
  154. root.SetAttribute(Keywords.MSD_DATATYPE, Keywords.MSDNS, col.DataType.FullName);
  155. }
  156. else if ((dt.Length == 0) || bImplementsInullable || ((dt == Keywords.XSD_ANYTYPE) && (col.XmlDataType != Keywords.XSD_ANYTYPE))|| (col.DataType == typeof(DateTimeOffset))) {
  157. // in Whidbey, XmlDataTypeName function changed to return "anyType" for typeof(Object)
  158. // should still always hit this code path for all non-built in types
  159. // to handle version qualified typeof(Object) and other CDT objects correctly
  160. // we must write the output exactly the same way as we read it
  161. this.SetMSDataAttribute(root, col.DataType);
  162. }
  163. return;
  164. }
  165. if (0 == String.Compare(pd.Name, "Attribute", StringComparison.Ordinal)) {
  166. return;
  167. }
  168. }
  169. string textValue = pd.Converter.ConvertToString(propInst) ;
  170. root.SetAttribute(pd.Name, Keywords.MSDNS, textValue);
  171. return;
  172. }
  173. //
  174. internal static string XmlDataTypeName(Type type) {
  175. if (type == typeof(Char))
  176. return "_"; // has to have SimpleType in this column.
  177. if (type == typeof(Byte[]) || type == typeof(SqlBytes))
  178. return "base64Binary"; // has to have SimpleType in this column.
  179. if (type == typeof(DateTime) || type == typeof(SqlDateTime) )
  180. return "dateTime";
  181. if (type == typeof(TimeSpan))
  182. return "duration";
  183. if (type == typeof(Decimal)|| type == typeof(SqlDecimal) || type == typeof(SqlMoney))
  184. return "decimal";
  185. if (type == typeof(int))
  186. return "int";
  187. if (type == typeof(Boolean)|| type == typeof(SqlBoolean))
  188. return "boolean";
  189. if (type == typeof(Single)|| type == typeof(SqlSingle))
  190. return "float";
  191. if (type == typeof(double) || type == typeof(SqlDouble))
  192. return "double";
  193. if (type == typeof(SByte)|| type == typeof(SqlByte))
  194. return "byte";
  195. if (type == typeof(Byte))
  196. return "unsignedByte";
  197. if (type == typeof(Int16) || type == typeof(SqlInt16))
  198. return "short";
  199. if (type == typeof(Int32) || type == typeof(SqlInt32))
  200. return "int";
  201. if (type == typeof(Int64) || type == typeof(SqlInt64))
  202. return "long";
  203. if (type == typeof(UInt16))
  204. return "unsignedShort";
  205. if (type == typeof(UInt32))
  206. return "unsignedInt";
  207. if (type == typeof(UInt64))
  208. return "unsignedLong";
  209. if (type == typeof(System.Numerics.BigInteger))
  210. return Keywords.XSD_ANYTYPE; //"integer";
  211. if (type == typeof(Uri))
  212. return "anyURI";
  213. if (type == typeof(SqlBinary))
  214. return "hexBinary";
  215. if (type == typeof(string) ||type == typeof(SqlGuid) ||type == typeof(SqlString) || type == typeof(SqlChars))
  216. return "string";
  217. if (type == typeof(object) || type == typeof(SqlXml) || type == typeof(DateTimeOffset))
  218. return Keywords.XSD_ANYTYPE;
  219. return String.Empty;
  220. // by default, if we dont map anything, we will map to String
  221. // but I can not make Sql Types that will map to string be unmapped, because in schema , I will miss the second part and wont
  222. // be able to differenciate between string snd SqlString and others that map to String
  223. }
  224. private void GenerateConstraintNames(DataTable table, bool fromTable) {
  225. // if constraint created obased on relation and it is self related rel. then add constraint
  226. StringBuilder builder = null;
  227. foreach(Constraint constr in table.Constraints) {
  228. if (fromTable) {
  229. if (constr is ForeignKeyConstraint) { // if parent table does not exist , no need to create FKConst
  230. if (!_tables.Contains((DataTable)(((ForeignKeyConstraint)constr).RelatedTable))) {
  231. continue;
  232. }
  233. }
  234. }
  235. int nameInt = 0;
  236. string name = constr.ConstraintName;
  237. while (ConstraintNames.Contains(name)) {
  238. if (null == builder) {
  239. builder = new StringBuilder();
  240. }
  241. builder.Append(table.TableName).Append('_').Append(constr.ConstraintName);
  242. if (0 < nameInt) {
  243. builder.Append('_').Append(nameInt);
  244. }
  245. nameInt++;
  246. name = builder.ToString();
  247. builder.Length = 0;
  248. }
  249. ConstraintNames.Add(name);
  250. constr.SchemaName = name;
  251. }
  252. }
  253. private void GenerateConstraintNames(ArrayList tables) {
  254. for (int i = 0; i < tables.Count; i++) {
  255. GenerateConstraintNames((DataTable)tables[i], true);
  256. }
  257. }
  258. private void GenerateConstraintNames(DataSet ds) {
  259. foreach(DataTable dt in ds.Tables) {
  260. GenerateConstraintNames(dt, false);
  261. }
  262. }
  263. //Does the DS or ANY object in it have ExtendedProperties?
  264. private static bool _PropsNotEmpty(PropertyCollection props) {
  265. return props != null && props.Count != 0;
  266. }
  267. private bool HaveExtendedProperties(DataSet ds) {
  268. if(_PropsNotEmpty(ds.extendedProperties)) {
  269. return true;
  270. }
  271. for(int t = 0; t < ds.Tables.Count; t ++) {
  272. DataTable table = ds.Tables[t];
  273. if(_PropsNotEmpty(table.extendedProperties)) {
  274. return true;
  275. }
  276. for(int c = 0; c < table.Columns.Count; c ++) {
  277. if(_PropsNotEmpty(table.Columns[c].extendedProperties)) {
  278. return true;
  279. }
  280. }
  281. }
  282. // What is the best way to enumerate relations? from DataSet of from DataTable?
  283. for(int r = 0; r < ds.Relations.Count; r ++) {
  284. if(_PropsNotEmpty(ds.Relations[r].extendedProperties)) {
  285. return true;
  286. }
  287. }
  288. // What about constraints?
  289. return false;
  290. }// HaveExtendedProperties
  291. internal void WriteSchemaRoot(XmlDocument xd, XmlElement rootSchema, string targetNamespace) {
  292. /*
  293. if (_ds != null)
  294. rootSchema.SetAttribute(Keywords.XSDID, XmlConvert.EncodeLocalName(_ds.DataSetName));
  295. else
  296. rootSchema.SetAttribute(Keywords.XSDID, XmlConvert.EncodeLocalName("NewDataSet"));
  297. */
  298. if (!Common.ADP.IsEmpty(targetNamespace)) {
  299. rootSchema.SetAttribute(Keywords.TARGETNAMESPACE, targetNamespace );
  300. rootSchema.SetAttribute(Keywords.XMLNS_MSTNS, targetNamespace );
  301. }
  302. // Add the namespaces
  303. // rootSchema.SetAttribute(Keywords.XMLNS, Keywords.XSD_ATOM.String));
  304. rootSchema.SetAttribute(Keywords.XMLNS, targetNamespace);
  305. rootSchema.SetAttribute(Keywords.XMLNS_XSD, Keywords.XSDNS);
  306. rootSchema.SetAttribute(Keywords.XMLNS_MSDATA, Keywords.MSDNS);
  307. if((_ds != null) && (HaveExtendedProperties(_ds))) {
  308. rootSchema.SetAttribute(Keywords.XMLNS_MSPROP, Keywords.MSPROPNS);
  309. }
  310. if (!Common.ADP.IsEmpty(targetNamespace)) {
  311. rootSchema.SetAttribute(Keywords.XSD_ATTRIBUTEFORMDEFAULT, Keywords.QUALIFIED);
  312. rootSchema.SetAttribute(Keywords.XSD_ELEMENTFORMDEFAULT, Keywords.QUALIFIED);
  313. }
  314. }
  315. internal static void ValidateColumnMapping(Type columnType) {
  316. if (DataStorage.IsTypeCustomType(columnType)) {
  317. throw ExceptionBuilder.InvalidDataColumnMapping(columnType);
  318. }
  319. }
  320. internal void SetupAutoGenerated(DataSet ds){
  321. foreach (DataTable dt in ds.Tables)
  322. SetupAutoGenerated(dt);
  323. }
  324. internal void SetupAutoGenerated(ArrayList dt){
  325. for(int i = 0; i < dt.Count; i++) {
  326. SetupAutoGenerated((DataTable)dt[i]);
  327. }
  328. }
  329. internal void SetupAutoGenerated(DataTable dt){
  330. foreach (DataColumn col in dt.Columns) {
  331. if (AutoGenerated(col))
  332. autogenerated[col] = col;
  333. }
  334. foreach (Constraint cs in dt.Constraints) {
  335. ForeignKeyConstraint fk = (cs as ForeignKeyConstraint);
  336. if (null != fk) {
  337. if (AutoGenerated(fk))
  338. autogenerated[fk] = fk;
  339. else {
  340. if (autogenerated[fk.Columns[0]] != null)
  341. autogenerated[fk.Columns[0]] = null;
  342. if (autogenerated[fk.RelatedColumnsReference[0]] != null)
  343. autogenerated[fk.RelatedColumnsReference[0]] = null;
  344. // special case of the ghosted constraints:
  345. UniqueConstraint _constraint = (UniqueConstraint) fk.RelatedTable.Constraints.FindConstraint( new UniqueConstraint( "TEMP", fk.RelatedColumnsReference));
  346. if (_constraint == null)
  347. continue;
  348. if(autogenerated[_constraint] != null)
  349. autogenerated[_constraint] = null;
  350. if(autogenerated[_constraint.Key.ColumnsReference[0]] != null)
  351. autogenerated[_constraint.Key.ColumnsReference[0]] = null;
  352. }
  353. }
  354. else {
  355. UniqueConstraint unique = (UniqueConstraint) cs;
  356. if (AutoGenerated(unique))
  357. autogenerated[unique] = unique;
  358. else {
  359. if (autogenerated[unique.Key.ColumnsReference[0]] != null)
  360. autogenerated[unique.Key.ColumnsReference[0]] = null;
  361. }
  362. }
  363. }
  364. }
  365. private void CreateTablesHierarchy(DataTable dt) {
  366. // if (!dt.SerializeHierarchy)
  367. // return;
  368. foreach( DataRelation r in dt.ChildRelations ) {
  369. if (! _tables.Contains((DataTable)r.ChildTable)) {
  370. _tables.Add((DataTable)r.ChildTable);
  371. CreateTablesHierarchy(r.ChildTable);
  372. }
  373. }
  374. }
  375. private void CreateRelations(DataTable dt) {
  376. foreach( DataRelation r in dt.ChildRelations ) {
  377. if (! _relations.Contains((DataRelation)r)) {
  378. _relations.Add((DataRelation)r);
  379. // if (dt.SerializeHierarchy)
  380. CreateRelations(r.ChildTable);
  381. }
  382. }
  383. }
  384. private DataTable[] CreateToplevelTables() {
  385. ArrayList topTables = new ArrayList();
  386. for (int i = 0; i < _tables.Count; i++) {
  387. DataTable table =(DataTable) _tables[i];
  388. if (table.ParentRelations.Count == 0)
  389. topTables.Add(table);
  390. else {
  391. bool fNestedButNotSelfNested = false;
  392. for (int j = 0; j < table.ParentRelations.Count; j++) {
  393. if (table.ParentRelations[j].Nested) {
  394. if (table.ParentRelations[j].ParentTable == table) {
  395. fNestedButNotSelfNested = false;
  396. break;
  397. }
  398. fNestedButNotSelfNested = true;
  399. }
  400. }
  401. if (!fNestedButNotSelfNested)
  402. topTables.Add(table);
  403. }
  404. }
  405. if (topTables.Count == 0)
  406. return (new DataTable[0]);
  407. DataTable[] temp = new DataTable[topTables.Count];
  408. topTables.CopyTo(temp, 0);
  409. return temp;
  410. }
  411. // SxS: this method can generate XSD files if the input xmlWriter is XmlTextWriter or DataTextWriter and its underlying stream is FileStream
  412. // These XSDs are located in the same folder as the underlying stream's file path (see SetPath method).
  413. // These XSDs are not exposed out of this method, so ResourceExposure annotation is None.
  414. [ResourceExposure(ResourceScope.None)]
  415. [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
  416. internal void SchemaTree(XmlDocument xd, XmlWriter xmlWriter, DataSet ds, DataTable dt, bool writeHierarchy) {
  417. ConstraintNames = new ArrayList();
  418. autogenerated = new Hashtable();
  419. bool genSecondary = filePath != null; //null non-file based streams.
  420. dsElement = xd.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_ELEMENT, Keywords.XSDNS);
  421. DataTable [] top;
  422. bool fFlat = false;
  423. DataTable _dt = dt;
  424. if (ds != null) {
  425. _ds = ds;
  426. foreach(DataTable table in ds.Tables) {
  427. _tables.Add(table);
  428. }
  429. }
  430. else {
  431. if (dt.DataSet != null) {
  432. // preserve datatable's dataset to use for xml
  433. // if null it would write out document element instead of dt.DataSet.DataSetName
  434. _ds = dt.DataSet;
  435. }
  436. _tables.Add(dt);
  437. if (writeHierarchy) {
  438. CreateTablesHierarchy(dt);
  439. }
  440. }
  441. _dc = xd;
  442. namespaces = new Hashtable();
  443. prefixes = new Hashtable();
  444. XmlElement rootSchema = xd.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_SCHEMA, Keywords.XSDNS);
  445. _sRoot = rootSchema;
  446. // Need to writeid attribute on schema, as webservice relys on it for typeddataset deserialization
  447. // to get class name
  448. if (_ds != null) {
  449. rootSchema.SetAttribute(Keywords.XSDID, XmlConvert.EncodeLocalName(_ds.DataSetName));
  450. }
  451. else {
  452. rootSchema.SetAttribute(Keywords.XSDID, XmlConvert.EncodeLocalName("NewDataSet"));
  453. }
  454. if (_ds != null) {
  455. WriteSchemaRoot(xd, rootSchema, _ds.Namespace);
  456. }
  457. else {
  458. WriteSchemaRoot(xd, rootSchema, _dt.Namespace);
  459. }
  460. // register the root element and associated NS
  461. if (schFormat == SchemaFormat.Remoting) {
  462. if (_ds != null) {
  463. namespaces[_ds.Namespace] = rootSchema;
  464. }
  465. else {
  466. namespaces[_dt.Namespace] = rootSchema;
  467. }
  468. }
  469. if (schFormat != SchemaFormat.Remoting) {
  470. if (_ds != null) {
  471. namespaces[_ds.Namespace] = rootSchema;
  472. if (_ds.Namespace.Length == 0)
  473. prefixes[_ds.Namespace] = null;
  474. else {
  475. // generate a prefix for the dataset schema itself.
  476. rootSchema.SetAttribute(Keywords.XMLNS_MSTNS, _ds.Namespace );
  477. prefixes[_ds.Namespace] = "mstns";
  478. }
  479. }
  480. }
  481. // Generate all the constraint names
  482. if (ds != null)
  483. GenerateConstraintNames(ds);
  484. else
  485. GenerateConstraintNames(_tables);
  486. // Setup AutoGenerated table
  487. if (schFormat != SchemaFormat.Remoting) {
  488. if (ds != null) {
  489. SetupAutoGenerated(ds);
  490. }
  491. else {
  492. SetupAutoGenerated(_tables);
  493. }
  494. }
  495. //
  496. // Output all top level elements, which will recursively invoke to other tables.
  497. //
  498. top = ((ds != null) ? ds.TopLevelTables(true) : CreateToplevelTables());
  499. if (top.Length == 0 || schFormat == SchemaFormat.WebServiceSkipSchema || schFormat == SchemaFormat.RemotingSkipSchema) {
  500. // return an empty schema for now.
  501. // probably we need to throw an exception
  502. FillDataSetElement(xd, ds, dt);
  503. rootSchema.AppendChild(dsElement);
  504. AddXdoProperties(_ds, dsElement, xd );
  505. AddExtendedProperties(ds.extendedProperties, dsElement);
  506. xd.AppendChild(rootSchema);
  507. xd.Save(xmlWriter);
  508. xmlWriter.Flush();
  509. return ; // rootSchema content has already been pushed to xmlWriter
  510. }
  511. // if (schFormat != SchemaFormat.WebService && namespaces.Count > 1 && !genSecondary) {
  512. // rootSchema.SetAttribute(Keywords.MSD_FRAGMENTCOUNT, Keywords.MSDNS, namespaces.Count.ToString());
  513. // }
  514. // Fill out dataset element
  515. XmlElement dsCompositor = FillDataSetElement(xd, ds, dt);
  516. constraintSeparator = xd.CreateElement(Keywords.XSD_PREFIX, "SHOULDNOTBEHERE", Keywords.XSDNS);
  517. dsElement.AppendChild(constraintSeparator);
  518. // DataSet properties
  519. if (_ds != null) {
  520. AddXdoProperties(_ds, dsElement, xd );
  521. AddExtendedProperties(_ds.extendedProperties, dsElement);
  522. }
  523. for (int i = 0; i < top.Length; i++) {
  524. XmlElement el = HandleTable(top[i], xd, rootSchema);
  525. if (((_ds != null )&& (_ds.Namespace == top[i].Namespace)) || Common.ADP.IsEmpty(top[i].Namespace) || (schFormat == SchemaFormat.Remoting)) {
  526. bool fNestedInDataset = top[i].fNestedInDataset;
  527. if (((_ds != null )&& (_ds.Namespace.Length != 0)) && Common.ADP.IsEmpty(top[i].Namespace)) {
  528. fNestedInDataset = true;
  529. }
  530. // what if dt has two nested relation , one self nested , the other with dtParent
  531. if (top[i].SelfNested) { // regarding above check : is it selfnested!
  532. fNestedInDataset = false;
  533. }
  534. if (top[i].NestedParentsCount > 1) { // if it has multiple parents, it should be global
  535. fNestedInDataset = false;
  536. }
  537. if(fNestedInDataset) { //deal with maxOccurs properly
  538. if (top[i].MinOccurs != 1) {
  539. el.SetAttribute(Keywords.MINOCCURS, top[i].MinOccurs.ToString(CultureInfo.InvariantCulture));
  540. }
  541. if (top[i].MaxOccurs == -1){
  542. el.SetAttribute(Keywords.MAXOCCURS, Keywords.ZERO_OR_MORE);
  543. }
  544. else if (top[i].MaxOccurs != 1){
  545. el.SetAttribute(Keywords.MAXOCCURS, top[i].MaxOccurs.ToString(CultureInfo.InvariantCulture));
  546. }
  547. }
  548. if (!fNestedInDataset) {
  549. rootSchema.AppendChild(el);
  550. XmlElement node = xd.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_ELEMENT, Keywords.XSDNS);
  551. if ((_ds != null && _ds.Namespace == top[i].Namespace) || Common.ADP.IsEmpty(top[i].Namespace) || (schFormat == SchemaFormat.Remoting))
  552. node.SetAttribute(Keywords.REF, top[i].EncodedTableName);
  553. else
  554. node.SetAttribute(Keywords.REF, ((string)prefixes[top[i].Namespace])+':'+top[i].EncodedTableName);
  555. dsCompositor.AppendChild(node);
  556. }
  557. else
  558. dsCompositor.AppendChild(el);
  559. }
  560. else {
  561. AppendChildWithoutRef(rootSchema, top[i].Namespace, el, Keywords.XSD_ELEMENT);
  562. XmlElement node = xd.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_ELEMENT, Keywords.XSDNS);
  563. node.SetAttribute(Keywords.REF, ((string)prefixes[top[i].Namespace])+':'+top[i].EncodedTableName);
  564. dsCompositor.AppendChild(node);
  565. }
  566. }
  567. dsElement.RemoveChild(constraintSeparator);
  568. rootSchema.AppendChild(dsElement);
  569. // Output all non-heirarchical relations without constraints
  570. DataRelation [] rels = new DataRelation[0];
  571. if (ds != null && _tables.Count> 0) { // we need to make sure we want to write relation just for tables in list
  572. rels = new DataRelation[ds.Relations.Count];
  573. for (int i = 0 ; i < ds.Relations.Count ; i++) {
  574. rels[i] = ds.Relations[i];
  575. }
  576. }
  577. else if (writeHierarchy && _tables.Count > 0 ) {
  578. CreateRelations((DataTable)_tables[0]);
  579. rels = new DataRelation[_relations.Count];
  580. _relations.CopyTo(rels, 0);
  581. }
  582. XmlElement nodeAnn = null;
  583. XmlElement nodeApp = null;
  584. for (int i = 0; i < rels.Length; ++i) {
  585. DataRelation rel = rels[i];
  586. if (!rel.Nested || fFlat) {
  587. if (rel.ChildKeyConstraint == null) {
  588. if (nodeAnn == null) {
  589. nodeAnn = xd.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_ANNOTATION, Keywords.XSDNS);
  590. rootSchema.AppendChild(nodeAnn);
  591. nodeApp = xd.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_APPINFO, Keywords.XSDNS);
  592. nodeAnn.AppendChild(nodeApp);
  593. }
  594. Debug.Assert(nodeApp != null, "Need to create <application..> node first.");
  595. nodeApp.AppendChild(HandleRelation(rel, xd));
  596. }
  597. }
  598. }
  599. XmlComment comment = null;
  600. bool isMultipleNamespaceAndStreamingWriter = (namespaces.Count > 1 && !genSecondary);
  601. if (schFormat != SchemaFormat.Remoting && schFormat != SchemaFormat.RemotingSkipSchema) {
  602. // complete processing of rootSchema
  603. foreach (string ns in namespaces.Keys) {
  604. if (ns == ((_ds != null) ? _ds.Namespace : _dt.Namespace) || Common.ADP.IsEmpty(ns)) {
  605. continue;
  606. }
  607. XmlElement _import = xd.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_IMPORT, Keywords.XSDNS);
  608. _import.SetAttribute(Keywords.XSD_NAMESPACE, ns);
  609. if ( schFormat != SchemaFormat.WebService && !isMultipleNamespaceAndStreamingWriter) {
  610. _import.SetAttribute(Keywords.XSD_SCHEMALOCATION, fileName + "_" + prefixes[ns] + ".xsd");
  611. }
  612. ((XmlNode)rootSchema).PrependChild((XmlNode)_import);
  613. }
  614. if (schFormat != SchemaFormat.WebService && isMultipleNamespaceAndStreamingWriter) {
  615. rootSchema.SetAttribute(Keywords.MSD_FRAGMENTCOUNT, Keywords.MSDNS, namespaces.Count.ToString(CultureInfo.InvariantCulture));
  616. }
  617. // Post rootSchema content to xmlWriter.
  618. xd.AppendChild(rootSchema); // KB
  619. if (schFormat != SchemaFormat.WebService && isMultipleNamespaceAndStreamingWriter) {
  620. xd.WriteTo(xmlWriter);
  621. }
  622. else {
  623. xd.Save(xmlWriter);
  624. }
  625. xd.RemoveChild(rootSchema); //KB
  626. foreach(string ns in namespaces.Keys)
  627. {
  628. if (ns == ((_ds != null)?_ds.Namespace:_dt.Namespace) || Common.ADP.IsEmpty(ns)) {
  629. continue;
  630. }
  631. XmlWriter xw = null;
  632. if (!genSecondary) {
  633. xw = xmlWriter;
  634. }
  635. else {
  636. xw = new XmlTextWriter(filePath + fileName + "_" + prefixes[ns] + ".xsd", null);
  637. }
  638. try {
  639. if (genSecondary) {
  640. if (xw is XmlTextWriter) {
  641. ((XmlTextWriter)xw).Formatting = Formatting.Indented;
  642. }
  643. xw.WriteStartDocument(true);
  644. }
  645. XmlElement tNode = (XmlElement) namespaces[ns] ;
  646. _dc.AppendChild( tNode );
  647. foreach(string imp_ns in namespaces.Keys)
  648. {
  649. if (ns == imp_ns) {
  650. continue; // don't write out yourself
  651. }
  652. string prefix = (string) prefixes[imp_ns];
  653. if (prefix == null) { // only for dataset.Namespace == empty
  654. continue; // do nothing
  655. }
  656. tNode.SetAttribute("xmlns:"+prefix, imp_ns);
  657. XmlElement _import2 = _dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_IMPORT, Keywords.XSDNS);
  658. _import2.SetAttribute(Keywords.XSD_NAMESPACE, imp_ns);
  659. if ( schFormat != SchemaFormat.WebService && !isMultipleNamespaceAndStreamingWriter)
  660. {
  661. if (imp_ns == ((_ds != null)?_ds.Namespace:_dt.Namespace))
  662. _import2.SetAttribute(Keywords.XSD_SCHEMALOCATION, fileName + fileExt); // for the dataset namespace don't append anything
  663. else
  664. _import2.SetAttribute(Keywords.XSD_SCHEMALOCATION, fileName + "_" + prefix +".xsd");
  665. }
  666. ((XmlNode)tNode).PrependChild((XmlNode)_import2);
  667. }
  668. if (schFormat != SchemaFormat.WebService && isMultipleNamespaceAndStreamingWriter) {
  669. _dc.WriteTo(xw);
  670. }
  671. else {
  672. _dc.Save(xw);
  673. }
  674. _dc.RemoveChild( tNode );
  675. if (genSecondary) {
  676. xw.WriteEndDocument();
  677. }
  678. }
  679. finally {
  680. if (genSecondary) {
  681. xw.Close();
  682. }
  683. }
  684. }
  685. }
  686. else {
  687. xd.AppendChild(rootSchema);
  688. xd.Save(xmlWriter);
  689. }
  690. if (comment != null) {
  691. ((XmlNode)rootSchema).PrependChild((XmlNode)comment);
  692. }
  693. if (!genSecondary) {
  694. xmlWriter.Flush();
  695. }
  696. return;// rootSchema;
  697. }
  698. internal XmlElement SchemaTree(XmlDocument xd, DataTable dt) {
  699. dsElement = xd.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_ELEMENT, Keywords.XSDNS);
  700. ConstraintNames = new ArrayList();
  701. _ds = dt.DataSet;
  702. _dc = xd;
  703. namespaces = new Hashtable();
  704. prefixes = new Hashtable();
  705. if (schFormat != SchemaFormat.Remoting) {
  706. autogenerated = new Hashtable();
  707. }
  708. XmlElement rootSchema = xd.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_SCHEMA, Keywords.XSDNS);
  709. _sRoot = rootSchema;
  710. WriteSchemaRoot(xd, rootSchema, dt.Namespace);
  711. XmlElement dsCompositor = FillDataSetElement(xd, null, dt);
  712. constraintSeparator = xd.CreateElement(Keywords.XSD_PREFIX, "SHOULDNOTBEHERE", Keywords.XSDNS);
  713. dsElement.AppendChild(constraintSeparator);
  714. if (schFormat != SchemaFormat.Remoting) {
  715. if (_ds != null) {
  716. namespaces[_ds.Namespace] = rootSchema;
  717. if (_ds.Namespace.Length == 0) {
  718. prefixes[_ds.Namespace] = null;
  719. }
  720. else {
  721. // generate a prefix for the dataset schema itself.
  722. rootSchema.SetAttribute(Keywords.XMLNS_MSTNS, _ds.Namespace );
  723. prefixes[_ds.Namespace] = "mstns";
  724. }
  725. }
  726. else {
  727. namespaces[dt.Namespace] = rootSchema;
  728. if (dt.Namespace.Length == 0) {
  729. prefixes[dt.Namespace] = null;
  730. }
  731. else {
  732. // generate a prefix for the dataset schema itself.
  733. rootSchema.SetAttribute(Keywords.XMLNS_MSTNS, dt.Namespace );
  734. prefixes[dt.Namespace] = "mstns";
  735. }
  736. }
  737. }
  738. // Generate all the constraint names
  739. GenerateConstraintNames(dt, true);
  740. //
  741. // Output all top level elements, which will recursively invoke to other tables.
  742. //
  743. XmlElement el = HandleTable(dt, xd, rootSchema, false);
  744. rootSchema.AppendChild(el);
  745. dsElement.RemoveChild(constraintSeparator);
  746. rootSchema.AppendChild(dsElement);
  747. return rootSchema;
  748. }
  749. internal XmlElement FillDataSetElement(XmlDocument xd, DataSet ds, DataTable dt) {
  750. DataSet dataSet = (ds != null) ? ds : dt.DataSet;
  751. if (dataSet != null) {
  752. dsElement.SetAttribute(Keywords.NAME, XmlConvert.EncodeLocalName(dataSet.DataSetName));
  753. dsElement.SetAttribute(Keywords.MSD_ISDATASET, Keywords.MSDNS, Keywords.TRUE);
  754. if (ds == null)
  755. dsElement.SetAttribute(Keywords.MSD_MAINDATATABLE, Keywords.MSDNS, XmlConvert.EncodeLocalName(((dt.Namespace.Length == 0)?dt.TableName : (dt.Namespace + ":" + dt.TableName))));
  756. // Add CaseSensitive and locale properties
  757. if (dataSet.CaseSensitive) {
  758. dsElement.SetAttribute(Keywords.MSD_CASESENSITIVE, Keywords.MSDNS, Keywords.TRUE);
  759. }
  760. if (dataSet.ShouldSerializeLocale() || !dataSet.Locale.Equals(CultureInfo.CurrentCulture)) {
  761. dsElement.SetAttribute(Keywords.MSD_LOCALE, Keywords.MSDNS, dataSet.Locale.ToString());
  762. }
  763. else {
  764. dsElement.SetAttribute(Keywords.MSD_USECURRENTLOCALE, Keywords.MSDNS, Keywords.TRUE);
  765. }
  766. }
  767. else { // No DataSet
  768. if (dt != null) {
  769. dsElement.SetAttribute(Keywords.NAME, XmlConvert.EncodeLocalName("NewDataSet"));
  770. dsElement.SetAttribute(Keywords.MSD_ISDATASET, Keywords.MSDNS, Keywords.TRUE);
  771. dsElement.SetAttribute(Keywords.MSD_MAINDATATABLE, Keywords.MSDNS, XmlConvert.EncodeLocalName(((dt.Namespace.Length == 0)?dt.TableName : (dt.Namespace + ":" + dt.TableName))));
  772. if (dt.CaseSensitive) { // WebData 111631 :it is a bug to go and write casesensitive attrib as 'true', by default
  773. dsElement.SetAttribute(Keywords.MSD_CASESENSITIVE, Keywords.MSDNS, Keywords.TRUE);
  774. }
  775. if (dt.ShouldSerializeLocale() || !dt.Locale.Equals(CultureInfo.CurrentCulture)) {
  776. dsElement.SetAttribute(Keywords.MSD_LOCALE, Keywords.MSDNS, dt.Locale.ToString());
  777. }
  778. else {
  779. dsElement.SetAttribute(Keywords.MSD_USECURRENTLOCALE, Keywords.MSDNS, Keywords.TRUE);
  780. }
  781. }
  782. }
  783. XmlElement type = xd.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_COMPLEXTYPE, Keywords.XSDNS);
  784. dsElement.AppendChild(type);
  785. XmlElement compositor = xd.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_CHOICE, Keywords.XSDNS);
  786. compositor.SetAttribute(Keywords.MINOCCURS, Keywords.ZERO_DIGIT);
  787. compositor.SetAttribute(Keywords.MAXOCCURS, Keywords.ZERO_OR_MORE);
  788. type.AppendChild(compositor);
  789. return compositor;
  790. }
  791. internal void SetPath(XmlWriter xw){
  792. FileStream fs = null;
  793. DataTextWriter sw = xw as DataTextWriter;
  794. fs = (sw != null) ? sw.BaseStream as FileStream : null ;
  795. if (fs == null) {
  796. XmlTextWriter textw = xw as XmlTextWriter;
  797. if (textw == null)
  798. return;
  799. fs = textw.BaseStream as FileStream;
  800. if (fs == null)
  801. return;
  802. }
  803. this.filePath = Path.GetDirectoryName(fs.Name);
  804. this.fileName = Path.GetFileNameWithoutExtension(fs.Name);
  805. this.fileExt = Path.GetExtension(fs.Name);
  806. if (!Common.ADP.IsEmpty(this.filePath))
  807. this.filePath = filePath + "\\";
  808. }
  809. internal void Save(DataSet ds, XmlWriter xw) {
  810. Save(ds, (DataTable)null, xw);
  811. }
  812. internal void Save(DataTable dt, XmlWriter xw) {
  813. XmlDocument doc = new XmlDocument();
  814. if (schFormat == SchemaFormat.Public) {
  815. SetPath(xw);
  816. }
  817. XmlElement rootSchema = SchemaTree(doc, dt);
  818. doc.AppendChild( rootSchema );
  819. doc.Save(xw);
  820. }
  821. internal void Save(DataSet ds, DataTable dt, XmlWriter xw) {
  822. Save(ds, dt, xw, false);
  823. }
  824. internal void Save(DataSet ds, DataTable dt, XmlWriter xw, bool writeHierarchy) {
  825. this.Save(ds, dt, xw, writeHierarchy, null);
  826. }
  827. internal void Save(DataSet ds, DataTable dt, XmlWriter xw, bool writeHierarchy, Converter<Type, string> multipleTargetConverter)
  828. {
  829. this.targetConverter = multipleTargetConverter;
  830. XmlDocument doc = new XmlDocument();
  831. if (schFormat == SchemaFormat.Public) {
  832. SetPath(xw);
  833. }
  834. if (schFormat == SchemaFormat.WebServiceSkipSchema && xw.WriteState==WriteState.Element) {
  835. xw.WriteAttributeString(Keywords.MSD, Keywords.MSD_SCHEMASERIALIZATIONMODE, Keywords.MSDNS, Keywords.MSD_EXCLUDESCHEMA);
  836. }
  837. SchemaTree(doc, xw, ds, dt, writeHierarchy);
  838. }
  839. internal XmlElement HandleRelation(DataRelation rel, XmlDocument dc) {
  840. XmlElement root = dc.CreateElement(Keywords.MSD, Keywords.MSD_RELATION, Keywords.MSDNS);
  841. // convert relation name to valid xml name
  842. root.SetAttribute( Keywords.NAME, XmlConvert.EncodeLocalName( rel.RelationName ));
  843. root.SetAttribute(Keywords.MSD_PARENT, Keywords.MSDNS, rel.ParentKey.Table.EncodedTableName);
  844. root.SetAttribute(Keywords.MSD_CHILD, Keywords.MSDNS, rel.ChildKey.Table.EncodedTableName);
  845. if ((_ds == null) || (_ds.Tables.InternalIndexOf(rel.ParentKey.Table.TableName) ==-3))
  846. root.SetAttribute( Keywords.MSD_PARENTTABLENS, Keywords.MSDNS, rel.ParentKey.Table.Namespace);
  847. if ((_ds == null) || (_ds.Tables.InternalIndexOf(rel.ChildKey.Table.TableName) ==-3))
  848. root.SetAttribute( Keywords.MSD_CHILDTABLENS, Keywords.MSDNS, rel.ChildKey.Table.Namespace);
  849. DataColumn[] key = rel.ParentKey.ColumnsReference;
  850. string text = key[0].EncodedColumnName;
  851. StringBuilder builder = null;
  852. if (1 < key.Length) {
  853. builder = new StringBuilder();
  854. builder.Append(text);
  855. for (int i = 1; i < key.Length; i++) {
  856. builder.Append(Keywords.MSD_KEYFIELDSEP).Append(key[i].EncodedColumnName);
  857. }
  858. text = builder.ToString();
  859. }
  860. root.SetAttribute( Keywords.MSD_PARENTKEY, Keywords.MSDNS, text);
  861. key = rel.ChildKey.ColumnsReference;
  862. text = key[0].EncodedColumnName;
  863. if (1 < key.Length) {
  864. if (null != builder) {
  865. builder.Length = 0;
  866. }
  867. else {
  868. builder = new StringBuilder();
  869. }
  870. builder.Append(text);
  871. for (int i = 1; i < key.Length; i++) {
  872. builder.Append(Keywords.MSD_KEYFIELDSEP).Append(key[i].EncodedColumnName);
  873. }
  874. text = builder.ToString();
  875. }
  876. root.SetAttribute( Keywords.MSD_CHILDKEY, Keywords.MSDNS, text);
  877. AddExtendedProperties(rel.extendedProperties, root);
  878. return root;
  879. }
  880. private static XmlElement FindSimpleType(XmlElement schema, string name) {
  881. for (XmlNode n = schema.FirstChild; n != null; n = n.NextSibling) {
  882. if (n is XmlElement) {
  883. XmlElement e = (XmlElement) n;
  884. if(e.GetAttribute(Keywords.NAME) == name) {
  885. return e;
  886. }
  887. }
  888. }
  889. return null;
  890. }// FindSimpleType
  891. internal XmlElement GetSchema(string NamespaceURI) {
  892. XmlElement schemaEl = (XmlElement) namespaces[NamespaceURI];
  893. if (schemaEl == null) {
  894. schemaEl = _dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_SCHEMA, Keywords.XSDNS);
  895. WriteSchemaRoot(_dc, schemaEl, NamespaceURI);
  896. if (!Common.ADP.IsEmpty(NamespaceURI)) {
  897. string prefix = Keywords.APP+Convert.ToString(++prefixCount, CultureInfo.InvariantCulture);
  898. _sRoot.SetAttribute("xmlns:"+prefix, NamespaceURI);
  899. schemaEl.SetAttribute("xmlns:"+prefix, NamespaceURI);
  900. prefixes[NamespaceURI] = prefix;
  901. }
  902. namespaces[NamespaceURI] = schemaEl;
  903. }
  904. return schemaEl;
  905. }
  906. internal void HandleColumnType(DataColumn col, XmlDocument dc, XmlElement root, XmlElement schema) {
  907. string keyword = Keywords.TYPE;
  908. if (col.ColumnMapping == MappingType.SimpleContent)
  909. keyword = Keywords.BASE;
  910. if (col.SimpleType != null) {
  911. // generate simpleType node
  912. SimpleType stNode = col.SimpleType;
  913. while (stNode != null) {
  914. // for remoting, set the msdata:targetNamespace for the simpleType.
  915. XmlNode type;
  916. string name = stNode.Name;
  917. if (name != null && name.Length != 0) {
  918. // For remoting, always need to work with root schema's namespace
  919. string nSpace = (schFormat != SchemaFormat.Remoting) ? stNode.Namespace :
  920. (col.Table.DataSet != null ? col.Table.DataSet.Namespace : col.Table.Namespace);
  921. // for remoting we need to use columns NS, for other cases it is wrong to get Columns NS, we need to take type's namespace
  922. XmlElement schNode= GetSchema(nSpace);
  923. //SchNode To Ensure BaseSimpleType Prefix is Generated
  924. if (stNode.BaseSimpleType != null && stNode.BaseSimpleType.Namespace != null && stNode.BaseSimpleType.Namespace.Length>0)
  925. GetSchema(stNode.BaseSimpleType.Namespace); //it will ensure a prefix has been created for this namespace
  926. type = stNode.ToNode(dc, prefixes, (schFormat == SchemaFormat.Remoting));
  927. if (stNode == col.SimpleType) {
  928. string prefix = (string) prefixes[nSpace];
  929. // set the columns's type
  930. if (prefix != null && prefix.Length > 0) {
  931. if (schFormat != SchemaFormat.Remoting)
  932. root.SetAttribute(keyword,(prefix + ":" + name)); // look at below,this loop assumes we would be here just oen time: Its Wrong
  933. else // As all types (in remoting) belong to the same namespace, just write type name
  934. root.SetAttribute(keyword, name);
  935. }
  936. else
  937. root.SetAttribute(keyword, name);
  938. // set the root to the actual type, do not overwrite it in the iteration.
  939. }
  940. XmlElement elmSimpeType = FindSimpleType(schNode, name);
  941. if(elmSimpeType == null) {
  942. // if we don't have the defenition for this simpleType yet. Add it
  943. schNode.AppendChild(type);
  944. }else {
  945. #if DEBUG
  946. // [....]: TO DO: replace the constructor with IsEqual(XmlElement)
  947. // Debug.Assert(col.SimpleType.IsEqual(new SimpleType(elmSimpeType)), "simpleTypes with the same name have to be the same: "+name);
  948. #endif
  949. }
  950. }
  951. else {
  952. //SchNode To Ensure BaseSimpleType Prefix is Generated
  953. if (stNode.BaseSimpleType != null && stNode.BaseSimpleType.Namespace != null && stNode.BaseSimpleType.Namespace.Length>0)
  954. GetSchema(stNode.BaseSimpleType.Namespace); //it will ensure a prefix has been created for this namespace
  955. type = stNode.ToNode(dc, prefixes, schFormat == SchemaFormat.Remoting);
  956. root.AppendChild(type);
  957. }
  958. stNode = stNode.BaseSimpleType;
  959. }
  960. }
  961. else if (col.XmlDataType != null && col.XmlDataType.Length != 0 && XSDSchema.IsXsdType(col.XmlDataType)) {
  962. root.SetAttribute(keyword, XSDSchema.QualifiedName(col.XmlDataType));
  963. }
  964. else {
  965. string typeName = XmlDataTypeName(col.DataType); // do not update the hashtable, as it will not write msdata:DataType
  966. if (typeName == null || typeName.Length == 0) {
  967. if (col.DataType == typeof(Guid) || col.DataType == typeof(Type) ) {
  968. typeName = "string";
  969. }
  970. else {
  971. if (col.ColumnMapping == MappingType.Attribute) {
  972. XmlTreeGen.ValidateColumnMapping(col.DataType);
  973. }
  974. typeName = Keywords.XSD_ANYTYPE;
  975. }
  976. }
  977. root.SetAttribute(keyword, XSDSchema.QualifiedName(typeName));
  978. }
  979. }
  980. internal void AddColumnProperties(DataColumn col, XmlElement root){
  981. if (col.DataType != typeof(String)) {
  982. string dt = XmlDataTypeName(col.DataType);
  983. if ((col.IsSqlType && ((dt.Length == 0) || col.ImplementsINullable)) || (typeof(SqlXml) == col.DataType) || col.DataType == typeof(DateTimeOffset) || col.DataType == typeof(System.Numerics.BigInteger)) { // no need to check if it is Sql typee if it already implements INullable,
  984. root.SetAttribute(Keywords.MSD_DATATYPE, Keywords.MSDNS, col.DataType.FullName);
  985. }
  986. else if ((dt.Length == 0) || col.ImplementsINullable || ((dt == Keywords.XSD_ANYTYPE) && (col.XmlDataType != Keywords.XSD_ANYTYPE))) {
  987. // in Whidbey, XmlDataTypeName function changed to return "anyType" for typeof(Object)
  988. // should still always hit this code path for all non-built in types
  989. // to handle version qualified typeof(Object) and other CDT objects correctly
  990. // we must write the output exactly the same way as we read it
  991. this.SetMSDataAttribute(root, col.DataType);
  992. }
  993. }
  994. if (col.ReadOnly)
  995. root.SetAttribute("ReadOnly", Keywords.MSDNS, Keywords.TRUE);
  996. if (col.Expression.Length != 0)
  997. root.SetAttribute("Expression", Keywords.MSDNS, col.Expression);
  998. if (col.AutoIncrement) {
  999. root.SetAttribute("AutoIncrement", Keywords.MSDNS, Keywords.TRUE);
  1000. }
  1001. if (col.AutoIncrementSeed !=0 )
  1002. root.SetAttribute("AutoIncrementSeed", Keywords.MSDNS, col.AutoIncrementSeed.ToString(CultureInfo.InvariantCulture));
  1003. if (col.AutoIncrementStep !=1 )
  1004. root.SetAttribute("AutoIncrementStep", Keywords.MSDNS, col.AutoIncrementStep.ToString(CultureInfo.InvariantCulture));
  1005. if (col.Caption != col.ColumnName)
  1006. root.SetAttribute("Caption", Keywords.MSDNS, col.Caption);
  1007. if (col.Prefix.Length != 0)
  1008. root.SetAttribute("Prefix", Keywords.MSDNS, col.Prefix);
  1009. if (col.DataType == typeof(DateTime) && col.DateTimeMode != DataSetDateTime.UnspecifiedLocal) {
  1010. root.SetAttribute("DateTimeMode", Keywords.MSDNS, col.DateTimeMode.ToString());
  1011. }
  1012. }
  1013. private string FindTargetNamespace(DataTable table) {
  1014. string tgNamespace = table.TypeName.IsEmpty ? table.Namespace : table.TypeName.Namespace;
  1015. if (Common.ADP.IsEmpty(tgNamespace)) {
  1016. DataRelation [] nestedParentRelations = table.NestedParentRelations;
  1017. if (nestedParentRelations.Length != 0) {
  1018. for(int i = 0; i < nestedParentRelations.Length; i++) {
  1019. DataTable parentTable = nestedParentRelations[i].ParentTable;
  1020. if (table != parentTable) {// table can be self nested so it may go to infinite loop!
  1021. tgNamespace = FindTargetNamespace(parentTable);
  1022. if (!Common.ADP.IsEmpty(tgNamespace)) {
  1023. break;
  1024. }
  1025. }
  1026. }
  1027. }
  1028. else { // if it does not have any parent table , then it should inherit NS from DataSet
  1029. tgNamespace = _ds.Namespace;
  1030. }
  1031. }
  1032. return tgNamespace;
  1033. }
  1034. internal XmlElement HandleColumn(DataColumn col, XmlDocument dc, XmlElement schema, bool fWriteOrdinal) {
  1035. XmlElement root;
  1036. int minOccurs;
  1037. Debug.Assert(col.ColumnMapping != MappingType.SimpleContent , "Illegal state");
  1038. String refString = (col.ColumnMapping != MappingType.Element) ? Keywords.XSD_ATTRIBUTE : Keywords.XSD_ELEMENT;
  1039. root = dc.CreateElement(Keywords.XSD_PREFIX, refString, Keywords.XSDNS);
  1040. // First add any attributes.
  1041. root.SetAttribute( Keywords.NAME, col.EncodedColumnName);
  1042. if (col.Namespace.Length == 0) {
  1043. DataTable _table = col.Table;
  1044. // We need to travese the hirerarchy to find the targetnamepace
  1045. string tgNamespace = FindTargetNamespace(_table);
  1046. if (col.Namespace != tgNamespace) {
  1047. root.SetAttribute( Keywords.FORM, Keywords.UNQUALIFIED);
  1048. }
  1049. }
  1050. if (col.GetType() != typeof(DataColumn))
  1051. AddXdoProperties(col, root, dc);
  1052. else
  1053. AddColumnProperties(col, root);
  1054. AddExtendedProperties(col.extendedProperties, root);
  1055. HandleColumnType(col, dc, root, schema);
  1056. if (col.ColumnMapping == MappingType.Hidden) { // CDT / UDT can not be mapped to Hidden column
  1057. if (!col.AllowDBNull)
  1058. root.SetAttribute(Keywords.MSD_ALLOWDBNULL, Keywords.MSDNS, Keywords.FALSE);
  1059. if (!col.DefaultValueIsNull)
  1060. if (col.DataType == typeof(bool))
  1061. root.SetAttribute(Keywords.MSD_DEFAULTVALUE, Keywords.MSDNS, (bool)(col.DefaultValue)? Keywords.TRUE : Keywords.FALSE);
  1062. else
  1063. {
  1064. XmlTreeGen.ValidateColumnMapping(col.DataType);
  1065. root.SetAttribute(Keywords.MSD_DEFAULTVALUE, Keywords.MSDNS, col.ConvertObjectToXml(col.DefaultValue));
  1066. }
  1067. }
  1068. if ((!col.DefaultValueIsNull)&& (col.ColumnMapping != MappingType.Hidden)){
  1069. XmlTreeGen.ValidateColumnMapping(col.DataType);
  1070. if (col.ColumnMapping == MappingType.Attribute && !col.AllowDBNull ) {
  1071. if (col.DataType == typeof(bool)) {
  1072. root.SetAttribute(Keywords.MSD_DEFAULTVALUE, Keywords.MSDNS, (bool)(col.DefaultValue)? Keywords.TRUE : Keywords.FALSE);
  1073. }
  1074. else { // CDT / UDT columns cn not be mapped to Attribute also
  1075. root.SetAttribute(Keywords.MSD_DEFAULTVALUE, Keywords.MSDNS, col.ConvertObjectToXml(col.DefaultValue));
  1076. }
  1077. }
  1078. else { // Element Column : need to handle CDT
  1079. if (col.DataType == typeof(bool)) {
  1080. root.SetAttribute(Keywords.DEFAULT, (bool)(col.DefaultValue)? Keywords.TRUE : Keywords.FALSE);
  1081. }
  1082. else {
  1083. if (!col.IsCustomType) { // built in type
  1084. root.SetAttribute(Keywords.DEFAULT, col.ConvertObjectToXml(col.DefaultValue));
  1085. }
  1086. else { // UDT column
  1087. }
  1088. }
  1089. }
  1090. }
  1091. if (schFormat == SchemaFormat.Remoting)
  1092. root.SetAttribute( Keywords.TARGETNAMESPACE, Keywords.MSDNS, col.Namespace);
  1093. else {
  1094. if ((col.Namespace != (col.Table.TypeName.IsEmpty ? col.Table.Namespace : col.Table.TypeName.Namespace)) && (col.Namespace.Length != 0))
  1095. {
  1096. XmlElement schNode = GetSchema(col.Namespace);
  1097. if (FindTypeNode(schNode, col.EncodedColumnName) == null)
  1098. schNode.AppendChild(root);
  1099. root = _dc.CreateElement(Keywords.XSD_PREFIX, refString, Keywords.XSDNS);
  1100. root.SetAttribute( Keywords.REF, prefixes[ col.Namespace]+":"+ col.EncodedColumnName);
  1101. if (col.Table.Namespace!=_ds.Namespace) {
  1102. string prefix = (string)prefixes[col.Namespace];
  1103. XmlElement tNode = GetSchema(col.Table.Namespace);
  1104. }
  1105. }
  1106. }
  1107. minOccurs = (col.AllowDBNull) ? 0 : 1;
  1108. // [....] 2001 change
  1109. if (col.ColumnMapping == MappingType.Attribute && minOccurs != 0)
  1110. root.SetAttribute(Keywords.USE, Keywords.REQUIRED);
  1111. if (col.ColumnMapping == MappingType.Hidden) {
  1112. root.SetAttribute(Keywords.USE, Keywords.PROHIBITED);
  1113. }
  1114. else
  1115. if (col.ColumnMapping != MappingType.Attribute && minOccurs != 1)
  1116. root.SetAttribute(Keywords.MINOCCURS, minOccurs.ToString(CultureInfo.InvariantCulture));
  1117. if ((col.ColumnMapping == MappingType.Element) && fWriteOrdinal)
  1118. root.SetAttribute(Keywords.MSD_ORDINAL,Keywords.MSDNS, col.Ordinal.ToString(CultureInfo.InvariantCulture));
  1119. return root;
  1120. }
  1121. internal static string TranslateAcceptRejectRule( AcceptRejectRule rule ) {
  1122. switch (rule) {
  1123. case AcceptRejectRule.Cascade: return "Cascade";
  1124. case AcceptRejectRule.None: return "None";
  1125. default: return null;
  1126. }
  1127. }
  1128. internal static string TranslateRule( Rule rule ) {
  1129. switch (rule) {
  1130. case Rule.Cascade: return "Cascade";
  1131. case Rule.None: return "None";
  1132. case Rule.SetNull: return "SetNull";
  1133. case Rule.SetDefault: return "SetDefault";
  1134. default: return null;
  1135. }
  1136. }
  1137. internal void AppendChildWithoutRef(XmlElement node, string Namespace, XmlElement el, string refString) {
  1138. XmlElement schNode = GetSchema(Namespace);
  1139. if (FindTypeNode(schNode, el.GetAttribute(Keywords.NAME)) == null)
  1140. schNode.AppendChild(el);
  1141. }
  1142. internal XmlElement FindTypeNode(XmlElement node, string strType) {
  1143. if (node == null)
  1144. return null;
  1145. for (XmlNode n = node.FirstChild; n != null; n = n.NextSibling) {
  1146. if (!(n is XmlElement))
  1147. continue;
  1148. XmlElement child = (XmlElement) n;
  1149. if (XSDSchema.FEqualIdentity(child, Keywords.XSD_ELEMENT, Keywords.XSDNS) ||
  1150. XSDSchema.FEqualIdentity(child, Keywords.XSD_ATTRIBUTE, Keywords.XSDNS) ||
  1151. XSDSchema.FEqualIdentity(child, Keywords.XSD_COMPLEXTYPE, Keywords.XSDNS) ||
  1152. XSDSchema.FEqualIdentity(child, Keywords.XSD_SIMPLETYPE, Keywords.XSDNS)) {
  1153. if (child.GetAttribute(Keywords.NAME) == strType)
  1154. return child;
  1155. }
  1156. }
  1157. return null;
  1158. }
  1159. internal XmlElement HandleTable(DataTable table, XmlDocument dc, XmlElement schema) {
  1160. return HandleTable(table, dc, schema, true);
  1161. }
  1162. // we write out column Ordinals only if the table contains columns
  1163. // that map both to Attributes and Elements
  1164. private bool HasMixedColumns(DataTable table) {
  1165. bool hasAttributes = false;
  1166. bool hasElements = false;
  1167. foreach(DataColumn col in table.Columns) {
  1168. if (!hasElements && col.ColumnMapping == MappingType.Element)
  1169. hasElements = true;
  1170. if (!hasAttributes && (col.ColumnMapping == MappingType.Attribute || col.ColumnMapping == MappingType.Hidden))
  1171. hasAttributes = !AutoGenerated(col);
  1172. if (hasAttributes && hasElements)
  1173. return true;
  1174. }
  1175. return false;
  1176. }
  1177. internal static bool AutoGenerated(DataColumn col) {
  1178. // for now we use just this simple logic for the columns.
  1179. if (col.ColumnMapping != MappingType.Hidden)
  1180. return false;
  1181. if (col.DataType != typeof(int))
  1182. return false;
  1183. string generatedname = col.Table.TableName+"_Id";
  1184. if ((col.ColumnName == generatedname) || (col.ColumnName == generatedname+"_0"))
  1185. return true;
  1186. generatedname = "";
  1187. foreach (DataRelation rel in col.Table.ParentRelations) {
  1188. if (!rel.Nested)
  1189. continue;
  1190. if (rel.ChildColumnsReference.Length != 1)
  1191. continue;
  1192. if (rel.ChildColumnsReference[0] != col)
  1193. continue;
  1194. if (rel.ParentColumnsReference.Length != 1)
  1195. continue;
  1196. //ok if we are here it means that we have a 1column-1column relation
  1197. generatedname = rel.ParentColumnsReference[0].Table.TableName+"_Id";
  1198. }
  1199. if ((col.ColumnName == generatedname) || (col.ColumnName == generatedname+"_0"))
  1200. return true;
  1201. return false;
  1202. }
  1203. internal static bool AutoGenerated(DataRelation rel) {
  1204. string rName = rel.ParentTable.TableName + "_" + rel.ChildTable.TableName;
  1205. if (!rel.RelationName.StartsWith(rName, StringComparison.Ordinal))
  1206. return false;
  1207. if (rel.ExtendedProperties.Count > 0)
  1208. return false;
  1209. return true;
  1210. }
  1211. internal static bool AutoGenerated(UniqueConstraint unique) {
  1212. // for now we use just this simple logic for the columns.
  1213. if (!unique.ConstraintName.StartsWith("Constraint", StringComparison.Ordinal))
  1214. return false;
  1215. if (unique.Key.ColumnsReference.Length !=1)
  1216. return false;
  1217. if (unique.ExtendedProperties.Count > 0)
  1218. return false;
  1219. return AutoGenerated(unique.Key.ColumnsReference[0]);
  1220. }
  1221. private bool AutoGenerated(ForeignKeyConstraint fk) {
  1222. return AutoGenerated(fk, true);
  1223. }
  1224. internal static bool AutoGenerated(ForeignKeyConstraint fk, bool checkRelation) {
  1225. // for now we use just this simple logic for the columns.
  1226. DataRelation rel = fk.FindParentRelation();
  1227. if (checkRelation) {
  1228. if (rel == null)
  1229. return false; // otherwise roundtrip will create column
  1230. if (!AutoGenerated(rel))
  1231. return false;
  1232. if (rel.RelationName != fk.ConstraintName)
  1233. return false;
  1234. }
  1235. if (fk.ExtendedProperties.Count > 0)
  1236. return false;
  1237. if (fk.AcceptRejectRule != AcceptRejectRule.None)
  1238. return false;
  1239. if (fk.DeleteRule != Rule.Cascade)
  1240. return false;
  1241. if (fk.DeleteRule != Rule.Cascade)
  1242. return false;
  1243. if (fk.RelatedColumnsReference.Length !=1)
  1244. return false;
  1245. return AutoGenerated(fk.RelatedColumnsReference[0]);
  1246. }
  1247. private bool IsAutoGenerated(object o) {
  1248. if (schFormat != SchemaFormat.Remoting)
  1249. return autogenerated[o]!=null;
  1250. return false;
  1251. }
  1252. internal XmlElement HandleTable(DataTable table, XmlDocument dc, XmlElement schema, bool genNested) {
  1253. XmlElement root = dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_ELEMENT, Keywords.XSDNS);
  1254. bool fWriteOrdinals = false;
  1255. bool fUnqualified = false;
  1256. if (((table.DataSet == null) || (_ds!= null && table.Namespace != _ds.Namespace)) && (schFormat == SchemaFormat.Remoting))
  1257. root.SetAttribute( Keywords.TARGETNAMESPACE, Keywords.MSDNS, table.Namespace);
  1258. // First add any attributes.
  1259. root.SetAttribute( Keywords.NAME, table.EncodedTableName );
  1260. if (table.Namespace.Length == 0) {
  1261. DataTable _table = table;
  1262. string tgNamespace = _table.Namespace;
  1263. while (Common.ADP.IsEmpty(tgNamespace)) {
  1264. DataRelation [] nestedParentRelations = _table.NestedParentRelations;
  1265. if (nestedParentRelations.Length == 0){
  1266. tgNamespace = (_ds != null) ?_ds.Namespace : "";
  1267. break;
  1268. }
  1269. int nestedparentPosition = -1; // it is find non-self-nested-parent
  1270. for(int i = 0; i < nestedParentRelations.Length; i++) {
  1271. if (nestedParentRelations[i].ParentTable != _table) {
  1272. nestedparentPosition = i;
  1273. break;
  1274. }
  1275. }
  1276. if (nestedparentPosition == -1) {
  1277. break;
  1278. }
  1279. else {
  1280. _table = nestedParentRelations[nestedparentPosition].ParentTable;
  1281. }
  1282. tgNamespace = _table.Namespace;
  1283. }
  1284. if (table.Namespace != tgNamespace) {
  1285. root.SetAttribute( Keywords.FORM, Keywords.UNQUALIFIED);
  1286. fUnqualified = true;
  1287. }
  1288. }
  1289. if (table.ShouldSerializeCaseSensitive()) {
  1290. root.SetAttribute(Keywords.MSD_CASESENSITIVE, Keywords.MSDNS, table.CaseSensitive.ToString(CultureInfo.InvariantCulture));
  1291. }
  1292. if (table.ShouldSerializeLocale()) {
  1293. root.SetAttribute(Keywords.MSD_LOCALE, Keywords.MSDNS, table.Locale.ToString());
  1294. }
  1295. AddXdoProperties(table, root, dc);
  1296. DataColumnCollection columns = table.Columns;
  1297. int cCount = columns.Count;
  1298. int realCount = 0;
  1299. if (cCount ==1 || cCount ==2)
  1300. for (int i = 0; i < cCount; i++) {
  1301. DataColumn col = columns[i];
  1302. if (col.ColumnMapping == MappingType.Hidden) {
  1303. DataRelationCollection childRelations = table.ChildRelations;
  1304. for (int j = 0; j < childRelations.Count; j++) {
  1305. if (childRelations[j].Nested && childRelations[j].ParentKey.ColumnsReference.Length == 1 && childRelations[j].ParentKey.ColumnsReference[0] == col)
  1306. realCount++;
  1307. }
  1308. }
  1309. if (col.ColumnMapping == MappingType.Element)
  1310. realCount++;
  1311. }
  1312. if ((table.repeatableElement) && (realCount ==1)) {
  1313. // I only have 1 column and that gives me
  1314. // the type for this element
  1315. DataColumn col = table.Columns[0];
  1316. string _typeName = XmlDataTypeName(col.DataType);
  1317. if (_typeName == null || _typeName.Length == 0) {
  1318. _typeName = Keywords.XSD_ANYTYPE;
  1319. }
  1320. root.SetAttribute(Keywords.TYPE, XSDSchema.QualifiedName(_typeName));
  1321. return root;
  1322. }
  1323. // Now add the type information nested inside the element or global.
  1324. XmlElement type = dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_COMPLEXTYPE, Keywords.XSDNS);
  1325. if (!table.TypeName.IsEmpty && schFormat != SchemaFormat.Remoting) {
  1326. XmlElement typeSchema = GetSchema(table.TypeName.Namespace);
  1327. if (Common.ADP.IsEmpty(table.TypeName.Namespace)) {
  1328. if (_ds == null)
  1329. typeSchema = GetSchema(table.Namespace);
  1330. else
  1331. typeSchema = fUnqualified ? GetSchema(_ds.Namespace): GetSchema(table.Namespace);
  1332. }
  1333. if (FindTypeNode(typeSchema, table.TypeName.Name) == null)
  1334. typeSchema.AppendChild(type);
  1335. type.SetAttribute(Keywords.NAME, table.TypeName.Name);
  1336. }
  1337. else {
  1338. root.AppendChild(type);
  1339. }
  1340. if (!table.TypeName.IsEmpty) {
  1341. if (schFormat != SchemaFormat.Remoting)
  1342. root.SetAttribute( Keywords.TYPE, NewDiffgramGen.QualifiedName((string)prefixes[table.TypeName.Namespace], table.TypeName.Name) );
  1343. // Bug 108292: Since we always write complex type as annonymous type, DO NOT WRITE ITS NAME
  1344. // DO NOT REVERT THIS CHANGE
  1345. }
  1346. XmlElement compositor = null;
  1347. DataColumn colTxt = table.XmlText;
  1348. if (colTxt != null) {
  1349. XmlElement sc = dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_SIMPLECONTENT , Keywords.XSDNS);
  1350. if (colTxt.GetType() != typeof(DataColumn))
  1351. AddXdoProperties(colTxt, sc, dc);
  1352. else
  1353. AddColumnProperties(colTxt, sc);
  1354. AddExtendedProperties(colTxt.extendedProperties, sc);
  1355. if (colTxt.AllowDBNull)
  1356. root.SetAttribute(Keywords.XSD_NILLABLE, String.Empty, Keywords.TRUE);
  1357. if (!colTxt.DefaultValueIsNull)
  1358. {
  1359. XmlTreeGen.ValidateColumnMapping(colTxt.DataType);
  1360. sc.SetAttribute(Keywords.MSD_DEFAULTVALUE, Keywords.MSDNS, colTxt.ConvertObjectToXml(colTxt.DefaultValue));
  1361. }
  1362. sc.SetAttribute(Keywords.MSD_COLUMNNAME, Keywords.MSDNS, colTxt.ColumnName);
  1363. sc.SetAttribute(Keywords.MSD_ORDINAL, Keywords.MSDNS, colTxt.Ordinal.ToString(CultureInfo.InvariantCulture));
  1364. type.AppendChild (sc);
  1365. XmlElement ext = dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_EXTENSION, Keywords.XSDNS);
  1366. sc.AppendChild(ext);
  1367. HandleColumnType(colTxt, dc, ext, schema);
  1368. type = ext;
  1369. }
  1370. compositor = dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_SEQUENCE, Keywords.XSDNS);
  1371. type.AppendChild(compositor);
  1372. fWriteOrdinals = HasMixedColumns(table);
  1373. for (int i = 0; i < cCount; i++) {
  1374. DataColumn col = columns[i];
  1375. if (col.ColumnMapping == MappingType.SimpleContent)
  1376. continue;
  1377. if (col.ColumnMapping == MappingType.Attribute || col.ColumnMapping == MappingType.Element || col.ColumnMapping == MappingType.Hidden ) {
  1378. if (IsAutoGenerated(col)) // skip automanifactured columns
  1379. continue;
  1380. bool isAttribute = col.ColumnMapping != MappingType.Element;
  1381. XmlElement el = HandleColumn(col, dc, schema, fWriteOrdinals);
  1382. XmlElement node = isAttribute ? type : compositor;
  1383. //bool flag = isAttribute ? col.Namespace == "" : col.Namespace == table.Namespace;
  1384. node.AppendChild(el);
  1385. }
  1386. }
  1387. if ((table.XmlText == null) && (genNested)) {
  1388. DataRelationCollection childRelations = table.ChildRelations;
  1389. for (int j = 0; j < childRelations.Count; j++) {
  1390. XmlElement NestedTable;
  1391. if (!childRelations[j].Nested)
  1392. continue;
  1393. DataTable childTable = childRelations[j].ChildTable;
  1394. if (childTable == table) { // self join
  1395. NestedTable = dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_ELEMENT, Keywords.XSDNS);
  1396. NestedTable.SetAttribute( Keywords.REF, table.EncodedTableName );
  1397. }
  1398. else if (childTable.NestedParentsCount >1 ) { // skip relations with multiple parents
  1399. NestedTable = dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_ELEMENT, Keywords.XSDNS);
  1400. NestedTable.SetAttribute( Keywords.REF, childTable.EncodedTableName);
  1401. }
  1402. else
  1403. NestedTable = HandleTable(childTable, dc, schema);
  1404. if (childTable.Namespace == table.Namespace) {
  1405. NestedTable.SetAttribute(Keywords.MINOCCURS , "0");
  1406. NestedTable.SetAttribute(Keywords.MAXOCCURS , Keywords.ZERO_OR_MORE);
  1407. }
  1408. if ((childTable.Namespace == table.Namespace) || (childTable.Namespace.Length == 0) || schFormat == SchemaFormat.Remoting) {
  1409. compositor.AppendChild(NestedTable);
  1410. }
  1411. else {
  1412. if (childTable.NestedParentsCount <= 1 )
  1413. GetSchema(childTable.Namespace).AppendChild(NestedTable);
  1414. NestedTable = dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_ELEMENT, Keywords.XSDNS);
  1415. NestedTable.SetAttribute( Keywords.REF, ((string)prefixes[childTable.Namespace])+':'+childTable.EncodedTableName);
  1416. compositor.AppendChild(NestedTable);
  1417. }
  1418. if (childRelations[j].ChildKeyConstraint != null)
  1419. continue; // we write the relation using the constraint
  1420. XmlElement nodeAnn = _dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_ANNOTATION, Keywords.XSDNS);
  1421. NestedTable.PrependChild(nodeAnn);
  1422. XmlElement nodeApp = _dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_APPINFO, Keywords.XSDNS);
  1423. nodeAnn.AppendChild(nodeApp);
  1424. nodeApp.AppendChild(HandleRelation(childRelations[j], dc));
  1425. }
  1426. }
  1427. if (compositor != null)
  1428. if (!compositor.HasChildNodes)
  1429. type.RemoveChild(compositor);
  1430. // Output all constraints.
  1431. ConstraintCollection constraints = table.Constraints;
  1432. XmlElement selector, field;
  1433. String xpathprefix = (_ds != null)? (_ds.Namespace.Length != 0 ? Keywords.MSTNS_PREFIX : String.Empty) : String.Empty;
  1434. if (schFormat != SchemaFormat.Remoting) {
  1435. GetSchema(table.Namespace); // to ensure prefix handling
  1436. xpathprefix = table.Namespace.Length != 0 ? (string) prefixes[table.Namespace] +':' : String.Empty;
  1437. }
  1438. for (int i = 0; i < constraints.Count; i++) {
  1439. XmlElement constraint = null;
  1440. DataColumn[] fields;
  1441. if (constraints[i] is UniqueConstraint) {
  1442. UniqueConstraint unique = (UniqueConstraint)constraints[i];
  1443. if (IsAutoGenerated(unique))
  1444. continue;
  1445. // special case of the ghosted constraints:
  1446. fields = unique.Key.ColumnsReference;
  1447. constraint = dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_UNIQUE, Keywords.XSDNS);
  1448. if ((_ds == null) || (_ds.Tables.InternalIndexOf(table.TableName) ==-3))
  1449. constraint.SetAttribute( Keywords.MSD_TABLENS, Keywords.MSDNS, table.Namespace);
  1450. // convert constraint name to valid xml name
  1451. constraint.SetAttribute( Keywords.NAME, XmlConvert.EncodeLocalName( unique.SchemaName ));
  1452. if (unique.ConstraintName != unique.SchemaName)
  1453. constraint.SetAttribute(Keywords.MSD_CONSTRAINTNAME, Keywords.MSDNS, unique.ConstraintName);
  1454. AddExtendedProperties(unique.extendedProperties, constraint);
  1455. selector = dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_SELECTOR, Keywords.XSDNS);
  1456. selector.SetAttribute(Keywords.XSD_XPATH, ".//"+xpathprefix+table.EncodedTableName);
  1457. constraint.AppendChild(selector);
  1458. if (unique.IsPrimaryKey) {
  1459. constraint.SetAttribute(Keywords.MSD_PRIMARYKEY, Keywords.MSDNS, Keywords.TRUE);
  1460. }
  1461. if (0 < fields.Length) {
  1462. StringBuilder encodedName = new StringBuilder();
  1463. for (int k = 0; k < fields.Length; k++) {
  1464. encodedName.Length = 0;
  1465. if (schFormat != SchemaFormat.Remoting) {
  1466. GetSchema(fields[k].Namespace);
  1467. if (!Common.ADP.IsEmpty(fields[k].Namespace)) {
  1468. encodedName.Append(prefixes[fields[k].Namespace]).Append(':');
  1469. }
  1470. encodedName.Append(fields[k].EncodedColumnName);
  1471. }
  1472. else {
  1473. encodedName.Append(xpathprefix).Append(fields[k].EncodedColumnName);
  1474. }
  1475. if ((fields[k].ColumnMapping == MappingType.Attribute) || (fields[k].ColumnMapping == MappingType.Hidden)) {
  1476. encodedName.Insert(0, '@');
  1477. }
  1478. field = dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_FIELD, Keywords.XSDNS);
  1479. field.SetAttribute(Keywords.XSD_XPATH, encodedName.ToString());
  1480. constraint.AppendChild(field);
  1481. }
  1482. }
  1483. dsElement.InsertBefore(constraint, constraintSeparator);
  1484. }
  1485. else if (constraints[i] is ForeignKeyConstraint && genNested) {
  1486. ForeignKeyConstraint foreign = (ForeignKeyConstraint)constraints[i];
  1487. if (_tables.Count > 0) {
  1488. if (!_tables.Contains(foreign.RelatedTable) || !_tables.Contains(foreign.Table))
  1489. continue;
  1490. }
  1491. if (IsAutoGenerated(foreign))
  1492. continue;
  1493. DataRelation rel = foreign.FindParentRelation();
  1494. // special case of the ghosted constraints:
  1495. fields = foreign.RelatedColumnsReference;
  1496. UniqueConstraint _constraint = (UniqueConstraint) foreign.RelatedTable.Constraints.FindConstraint( new UniqueConstraint( "TEMP", fields));
  1497. if (_constraint == null) {
  1498. constraint = dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_KEY, Keywords.XSDNS);
  1499. constraint.SetAttribute( Keywords.NAME, XmlConvert.EncodeLocalName( foreign.SchemaName ));
  1500. if ((_ds == null) || (_ds.Tables.InternalIndexOf(table.TableName) ==-3))
  1501. constraint.SetAttribute( Keywords.MSD_TABLENS, Keywords.MSDNS, table.Namespace);
  1502. selector = dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_SELECTOR, Keywords.XSDNS);
  1503. selector.SetAttribute(Keywords.XSD_XPATH, ".//"+xpathprefix+ foreign.RelatedTable.EncodedTableName);
  1504. constraint.AppendChild(selector);
  1505. if (0 < fields.Length) {
  1506. StringBuilder encodedName = new StringBuilder();
  1507. for (int k = 0; k < fields.Length; k++) {
  1508. encodedName.Length = 0;
  1509. if (schFormat != SchemaFormat.Remoting) {
  1510. GetSchema(fields[k].Namespace);
  1511. if (!Common.ADP.IsEmpty(fields[k].Namespace)) {
  1512. encodedName.Append(prefixes[fields[k].Namespace]).Append(':');
  1513. }
  1514. encodedName.Append(fields[k].EncodedColumnName);
  1515. }
  1516. else {
  1517. encodedName.Append(xpathprefix).Append(fields[k].EncodedColumnName);
  1518. }
  1519. if ((fields[k].ColumnMapping == MappingType.Attribute) || (fields[k].ColumnMapping == MappingType.Hidden)) {
  1520. encodedName.Insert(0, '@');
  1521. }
  1522. field = dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_FIELD, Keywords.XSDNS);
  1523. field.SetAttribute(Keywords.XSD_XPATH, encodedName.ToString());
  1524. constraint.AppendChild(field);
  1525. }
  1526. }
  1527. dsElement.InsertBefore(constraint, constraintSeparator);
  1528. }
  1529. constraint = dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_KEYREF, Keywords.XSDNS);
  1530. // convert constraint name to valid xml name
  1531. constraint.SetAttribute( Keywords.NAME,XmlConvert.EncodeLocalName( foreign.SchemaName ));
  1532. if ((_ds == null) || (_ds.Tables.InternalIndexOf(foreign.RelatedTable.TableName) == -3)) // if there is a conflicting name/namespace only
  1533. constraint.SetAttribute (Keywords.MSD_TABLENS, Keywords.MSDNS, foreign.Table.Namespace);
  1534. if (_constraint == null)
  1535. constraint.SetAttribute( Keywords.REFER, XmlConvert.EncodeLocalName( foreign.SchemaName ));
  1536. else
  1537. constraint.SetAttribute( Keywords.REFER, XmlConvert.EncodeLocalName( _constraint.SchemaName ));
  1538. AddExtendedProperties(foreign.extendedProperties, constraint, typeof(ForeignKeyConstraint));
  1539. if (foreign.ConstraintName != foreign.SchemaName)
  1540. constraint.SetAttribute(Keywords.MSD_CONSTRAINTNAME, Keywords.MSDNS, foreign.ConstraintName);
  1541. if (null == rel) {
  1542. constraint.SetAttribute(Keywords.MSD_CONSTRAINTONLY , Keywords.MSDNS, Keywords.TRUE );
  1543. }else {
  1544. if (rel.Nested)
  1545. constraint.SetAttribute(Keywords.MSD_ISNESTED, Keywords.MSDNS, Keywords.TRUE);
  1546. AddExtendedProperties(rel.extendedProperties, constraint, typeof(DataRelation));
  1547. if (foreign.ConstraintName != rel.RelationName) {
  1548. constraint.SetAttribute( Keywords.MSD_RELATIONNAME , Keywords.MSDNS, XmlConvert.EncodeLocalName( rel.RelationName ));
  1549. }
  1550. }
  1551. selector = dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_SELECTOR, Keywords.XSDNS);
  1552. selector.SetAttribute(Keywords.XSD_XPATH, ".//"+xpathprefix+table.EncodedTableName);
  1553. constraint.AppendChild(selector);
  1554. if (foreign.AcceptRejectRule != ForeignKeyConstraint.AcceptRejectRule_Default)
  1555. constraint.SetAttribute(Keywords.MSD_ACCEPTREJECTRULE, Keywords.MSDNS,
  1556. TranslateAcceptRejectRule(foreign.AcceptRejectRule) );
  1557. if (foreign.UpdateRule != ForeignKeyConstraint.Rule_Default)
  1558. constraint.SetAttribute( Keywords.MSD_UPDATERULE, Keywords.MSDNS, TranslateRule(foreign.UpdateRule) );
  1559. if (foreign.DeleteRule != ForeignKeyConstraint.Rule_Default)
  1560. constraint.SetAttribute( Keywords.MSD_DELETERULE, Keywords.MSDNS, TranslateRule(foreign.DeleteRule) );
  1561. fields = foreign.Columns;
  1562. if (0 < fields.Length) {
  1563. StringBuilder encodedName = new StringBuilder();
  1564. for (int k = 0; k < fields.Length; k++) {
  1565. encodedName.Length = 0;
  1566. if (schFormat != SchemaFormat.Remoting) {
  1567. GetSchema(fields[k].Namespace);
  1568. if (!Common.ADP.IsEmpty(fields[k].Namespace)) {
  1569. encodedName.Append(prefixes[fields[k].Namespace]).Append(':');
  1570. }
  1571. encodedName.Append(fields[k].EncodedColumnName);
  1572. }
  1573. else {
  1574. encodedName.Append(xpathprefix).Append(fields[k].EncodedColumnName);
  1575. }
  1576. if ((fields[k].ColumnMapping == MappingType.Attribute) || (fields[k].ColumnMapping == MappingType.Hidden)) {
  1577. encodedName.Insert(0, '@');
  1578. }
  1579. field = dc.CreateElement(Keywords.XSD_PREFIX, Keywords.XSD_FIELD, Keywords.XSDNS);
  1580. field.SetAttribute(Keywords.XSD_XPATH, encodedName.ToString());
  1581. constraint.AppendChild(field);
  1582. }
  1583. }
  1584. dsElement.InsertAfter(constraint, constraintSeparator);
  1585. }
  1586. }
  1587. AddExtendedProperties(table.extendedProperties, root);
  1588. return root;
  1589. }
  1590. /// <summary>
  1591. /// resolve the name from the type for schema output and set the msdata:Data attribute
  1592. /// </summary>
  1593. /// <param name="root"></param>
  1594. /// <param name="type">non-special type to resolve</param>
  1595. /// <returns>type.AssemblyQualifiedName or targeted to a different version</returns>
  1596. /// <exception cref="DataException">if multipleTargetConverter throws or returns an empty result</exception>
  1597. private void SetMSDataAttribute(XmlElement root, Type type)
  1598. {
  1599. string result = DataStorage.GetQualifiedName(type);
  1600. try
  1601. {
  1602. if (null != this.targetConverter)
  1603. {
  1604. result = this.targetConverter(type);
  1605. }
  1606. if (!String.IsNullOrEmpty(result))
  1607. {
  1608. // SetAttribute doesn't fail with invalid data, but the final XmlDocument.Save will fail later
  1609. // with the ArugmentException when calling the actual XmlWriter.SetAttribute
  1610. root.SetAttribute(Keywords.MSD_DATATYPE, Keywords.MSDNS, result);
  1611. }
  1612. }
  1613. catch (Exception ex)
  1614. {
  1615. if (Common.ADP.IsCatchableExceptionType(ex))
  1616. {
  1617. ExceptionBuilder.ThrowMultipleTargetConverter(ex);
  1618. }
  1619. throw;
  1620. }
  1621. if (String.IsNullOrEmpty(result))
  1622. {
  1623. ExceptionBuilder.ThrowMultipleTargetConverter(null);
  1624. }
  1625. }
  1626. }
  1627. internal sealed class NewDiffgramGen {
  1628. internal XmlDocument _doc;
  1629. internal DataSet _ds;
  1630. internal DataTable _dt;
  1631. internal XmlWriter _xmlw;
  1632. private bool fBefore = false;
  1633. private bool fErrors = false;
  1634. internal Hashtable rowsOrder = null;
  1635. ArrayList _tables = new ArrayList();
  1636. bool _writeHierarchy = false;
  1637. internal NewDiffgramGen(DataSet ds) {
  1638. _ds = ds;
  1639. _dt = null;
  1640. _doc = new XmlDocument();
  1641. for (int i = 0; i < ds.Tables.Count; i++) {
  1642. _tables.Add(ds.Tables[i]);
  1643. }
  1644. DoAssignments(_tables);
  1645. }
  1646. internal NewDiffgramGen(DataTable dt, bool writeHierarchy) {
  1647. _ds = null;
  1648. _dt = dt;
  1649. _doc = new XmlDocument();
  1650. _tables.Add(dt);
  1651. if (writeHierarchy) {
  1652. this._writeHierarchy = true;
  1653. CreateTableHierarchy(dt);
  1654. }
  1655. DoAssignments(_tables);
  1656. }
  1657. private void CreateTableHierarchy(DataTable dt) {
  1658. // if (!dt.SerializeHierarchy)
  1659. // return;
  1660. foreach( DataRelation r in dt.ChildRelations ) {
  1661. if (! _tables.Contains((DataTable)r.ChildTable)) {
  1662. _tables.Add((DataTable)r.ChildTable);
  1663. CreateTableHierarchy(r.ChildTable);
  1664. }
  1665. }
  1666. }
  1667. private void DoAssignments(ArrayList tables) {
  1668. int rows = 0;
  1669. for (int i = 0; i < tables.Count; i++) {
  1670. rows += ((DataTable)tables[i]).Rows.Count ;
  1671. }
  1672. rowsOrder = new Hashtable(rows);
  1673. for (int i = 0; i < tables.Count; i++) {
  1674. DataTable dt = (DataTable)tables[i];
  1675. DataRowCollection rc = dt.Rows;
  1676. rows = rc.Count ;
  1677. for (int j=0; j<rows; j++)
  1678. rowsOrder[rc[j]] = j;
  1679. }
  1680. }
  1681. private bool EmptyData() {
  1682. for (int i = 0; i < _tables.Count; i++) {
  1683. if (((DataTable)_tables[i]).Rows.Count > 0)
  1684. return false;
  1685. }
  1686. return true;
  1687. }
  1688. internal void Save(XmlWriter xmlw) {
  1689. Save (xmlw, null);
  1690. }
  1691. internal void Save(XmlWriter xmlw, DataTable table) {
  1692. _xmlw = DataTextWriter.CreateWriter(xmlw);
  1693. _xmlw.WriteStartElement(Keywords.DFF, Keywords.DIFFGRAM, Keywords.DFFNS);
  1694. _xmlw.WriteAttributeString(Keywords.XMLNS, Keywords.MSD, null, Keywords.MSDNS);
  1695. // _xmlw.WriteAttributeString(Keywords.XMLNS, Keywords.UPDG, null, Keywords.UPDGNS);
  1696. if (! EmptyData()) {
  1697. // write the datapart
  1698. if (table != null)
  1699. new XmlDataTreeWriter(table, this._writeHierarchy).SaveDiffgramData(_xmlw, rowsOrder);
  1700. else
  1701. new XmlDataTreeWriter(_ds).SaveDiffgramData(_xmlw, rowsOrder);
  1702. // Walk the xd using relational apis and create nodes in nodeRoot appropriately.
  1703. if (table==null) {
  1704. for (int i = 0; i < _ds.Tables.Count; ++i) {
  1705. GenerateTable(_ds.Tables[i]);
  1706. }
  1707. }
  1708. else {
  1709. for(int i = 0; i < _tables.Count; i++) {
  1710. GenerateTable((DataTable)_tables[i]);
  1711. }
  1712. }
  1713. if (fBefore)
  1714. _xmlw.WriteEndElement(); //SQL_BEFORE
  1715. if (table==null) {
  1716. for (int i = 0; i < _ds.Tables.Count; ++i) {
  1717. GenerateTableErrors(_ds.Tables[i]);
  1718. }
  1719. }
  1720. else {
  1721. for(int i = 0; i < _tables.Count; i++) {
  1722. GenerateTableErrors((DataTable)_tables[i]);
  1723. }
  1724. }
  1725. if (fErrors)
  1726. _xmlw.WriteEndElement(); //ERRORS
  1727. }
  1728. _xmlw.WriteEndElement();
  1729. _xmlw.Flush();
  1730. }
  1731. private void GenerateTable(DataTable table) {
  1732. int rowCount = table.Rows.Count;
  1733. if (rowCount <= 0)
  1734. return;
  1735. for (int rowNum = 0; rowNum < rowCount; ++rowNum)
  1736. GenerateRow(table.Rows[rowNum]);
  1737. }
  1738. private void GenerateTableErrors(DataTable table) {
  1739. int rowCount = table.Rows.Count;
  1740. int colCount = table.Columns.Count;
  1741. if (rowCount <= 0)
  1742. return;
  1743. for (int rowNum = 0; rowNum < rowCount; ++rowNum) {
  1744. bool tableName = false;
  1745. DataRow row = table.Rows[rowNum];
  1746. string prefix = (table.Namespace.Length != 0) ? table.Prefix : String.Empty;
  1747. if ((row.HasErrors) && (row.RowError.Length > 0)) {
  1748. if (!fErrors) {
  1749. _xmlw.WriteStartElement( Keywords.DFF, Keywords.MSD_ERRORS, Keywords.DFFNS );
  1750. fErrors = true;
  1751. }
  1752. _xmlw.WriteStartElement( prefix, row.Table.EncodedTableName, row.Table.Namespace);
  1753. _xmlw.WriteAttributeString( Keywords.DFF, Keywords.DIFFID, Keywords.DFFNS, row.Table.TableName+row.rowID.ToString(CultureInfo.InvariantCulture));
  1754. _xmlw.WriteAttributeString( Keywords.DFF, Keywords.MSD_ERROR, Keywords.DFFNS, row.RowError);
  1755. tableName = true;
  1756. }
  1757. if (colCount <=0)
  1758. continue;
  1759. for (int colNum = 0; colNum < colCount; ++colNum) {
  1760. DataColumn column = table.Columns[colNum];
  1761. string error = row.GetColumnError(column);
  1762. string columnPrefix = (column.Namespace.Length != 0) ? column.Prefix : String.Empty;
  1763. if (error == null || error.Length == 0) {
  1764. continue;
  1765. }
  1766. if (!tableName) {
  1767. if (!fErrors) {
  1768. _xmlw.WriteStartElement( Keywords.DFF, Keywords.MSD_ERRORS, Keywords.DFFNS );
  1769. fErrors = true;
  1770. }
  1771. _xmlw.WriteStartElement( prefix, row.Table.EncodedTableName, row.Table.Namespace);
  1772. _xmlw.WriteAttributeString( Keywords.DFF, Keywords.DIFFID, Keywords.DFFNS, row.Table.TableName+row.rowID.ToString(CultureInfo.InvariantCulture));
  1773. tableName = true;
  1774. }
  1775. _xmlw.WriteStartElement( columnPrefix, column.EncodedColumnName, column.Namespace);
  1776. _xmlw.WriteAttributeString( Keywords.DFF, Keywords.MSD_ERROR, Keywords.DFFNS, error);
  1777. _xmlw.WriteEndElement();
  1778. }
  1779. if(tableName)
  1780. _xmlw.WriteEndElement();
  1781. }
  1782. }
  1783. private void GenerateRow(DataRow row) {
  1784. DataRowState state = row.RowState;
  1785. if ((state == DataRowState.Unchanged ) || (state == DataRowState.Added)) {
  1786. return;
  1787. }
  1788. if (!fBefore) {
  1789. _xmlw.WriteStartElement( Keywords.DFF, Keywords.SQL_BEFORE, Keywords.DFFNS);
  1790. fBefore = true;
  1791. }
  1792. DataTable table = row.Table;
  1793. int colCount = table.Columns.Count;
  1794. string rowIDString = table.TableName+row.rowID.ToString(CultureInfo.InvariantCulture);
  1795. string parentId = null;
  1796. if ( (state == DataRowState.Deleted ) && (row.Table.NestedParentRelations.Length != 0)){
  1797. DataRow parentRow = row.GetNestedParentRow(DataRowVersion.Original);
  1798. if (parentRow != null) {
  1799. parentId = parentRow.Table.TableName+parentRow.rowID.ToString(CultureInfo.InvariantCulture);
  1800. }
  1801. }
  1802. string tablePrefix = (table.Namespace.Length != 0) ? table.Prefix : String.Empty;
  1803. // read value if the TextOnly column (if any)
  1804. object val = (table.XmlText == null ? DBNull.Value : row[table.XmlText, DataRowVersion.Original]);
  1805. //old row
  1806. _xmlw.WriteStartElement( tablePrefix, row.Table.EncodedTableName, row.Table.Namespace);
  1807. _xmlw.WriteAttributeString( Keywords.DFF, Keywords.DIFFID, Keywords.DFFNS, rowIDString);
  1808. if ( (state == DataRowState.Deleted ) && XmlDataTreeWriter.RowHasErrors(row))
  1809. _xmlw.WriteAttributeString( Keywords.DFF, Keywords.HASERRORS, Keywords.DFFNS, Keywords.TRUE);
  1810. if (parentId != null)
  1811. _xmlw.WriteAttributeString( Keywords.DFF, Keywords.DIFFPID, Keywords.DFFNS, parentId);
  1812. _xmlw.WriteAttributeString( Keywords.MSD, Keywords.ROWORDER, Keywords.MSDNS, rowsOrder[row].ToString());
  1813. for (int colNum = 0; colNum < colCount; ++colNum) {
  1814. if ((row.Table.Columns[colNum].ColumnMapping == MappingType.Attribute) ||
  1815. (row.Table.Columns[colNum].ColumnMapping == MappingType.Hidden))
  1816. GenerateColumn(row, row.Table.Columns[colNum], DataRowVersion.Original);
  1817. }
  1818. for (int colNum = 0; colNum < colCount; ++colNum) {
  1819. if ((row.Table.Columns[colNum].ColumnMapping == MappingType.Element) ||
  1820. (row.Table.Columns[colNum].ColumnMapping == MappingType.SimpleContent))
  1821. GenerateColumn(row, row.Table.Columns[colNum], DataRowVersion.Original);
  1822. }
  1823. _xmlw.WriteEndElement(); //old row
  1824. }
  1825. private void GenerateColumn(DataRow row, DataColumn col, DataRowVersion version) {
  1826. string value = null;
  1827. value = col.GetColumnValueAsString(row, version); // this is useless for CTD
  1828. if (value == null) {
  1829. if (col.ColumnMapping == MappingType.SimpleContent)
  1830. _xmlw.WriteAttributeString(Keywords.XSI, Keywords.XSI_NIL, Keywords.XSINS, Keywords.TRUE);
  1831. return;
  1832. }
  1833. string colPrefix = (col.Namespace.Length != 0) ? col.Prefix : String.Empty;
  1834. switch (col.ColumnMapping) {
  1835. case MappingType.Attribute:
  1836. _xmlw.WriteAttributeString(colPrefix, col.EncodedColumnName, col.Namespace, value);
  1837. break;
  1838. case MappingType.Hidden:
  1839. _xmlw.WriteAttributeString(Keywords.MSD, "hidden"+col.EncodedColumnName, Keywords.MSDNS, value);
  1840. break;
  1841. case MappingType.SimpleContent:
  1842. _xmlw.WriteString(value);
  1843. break;
  1844. case MappingType.Element:
  1845. bool startElementSkipped = true;
  1846. object columnValue = row[col, version];
  1847. // if the object is built in type or if it implements IXMLSerializable, write the start Element, otherwise
  1848. //(if CDT and does not implement IXmlSerializable) skip it
  1849. if (!col.IsCustomType || !col.IsValueCustomTypeInstance(columnValue) ||(typeof(IXmlSerializable).IsAssignableFrom(columnValue.GetType()))) {
  1850. _xmlw.WriteStartElement( colPrefix, col.EncodedColumnName, col.Namespace);
  1851. startElementSkipped = false;
  1852. }
  1853. Type valuesType = columnValue.GetType();
  1854. if (!col.IsCustomType ) { // if column's type is built in type CLR or SQLType
  1855. if(valuesType == typeof(char) || valuesType == typeof(string)) {
  1856. if (XmlDataTreeWriter.PreserveSpace(value)) {
  1857. _xmlw.WriteAttributeString(Keywords.XML, Keywords.SPACE, Keywords.XML_XMLNS, Keywords.PRESERVE);
  1858. }
  1859. }
  1860. _xmlw.WriteString(value);
  1861. }
  1862. else { // Columns type is CDT
  1863. if ((columnValue != DBNull.Value) && (!col.ImplementsINullable || !DataStorage.IsObjectSqlNull(columnValue))){
  1864. if (col.IsValueCustomTypeInstance(columnValue)/* && valuesType != typeof(Type)*/) {// value is also CDT
  1865. // if SkippedElement, ie does not implement IXMLSerializable: so No Polymorphysm Support.
  1866. if (!startElementSkipped && columnValue.GetType() != col.DataType) {
  1867. _xmlw.WriteAttributeString(Keywords.MSD, Keywords.MSD_INSTANCETYPE, Keywords.MSDNS, DataStorage.GetQualifiedName(valuesType));
  1868. }
  1869. if (!startElementSkipped) {
  1870. col.ConvertObjectToXml(columnValue, _xmlw, null); // XmlRootAttribute MUST be passed null
  1871. }
  1872. else{
  1873. // this guy does not implement IXmlSerializable, so we need to handle serialization via XmlSerializer
  1874. if (columnValue.GetType() != col.DataType) { // throw if polymorphism; not supported
  1875. throw ExceptionBuilder.PolymorphismNotSupported(valuesType.AssemblyQualifiedName);
  1876. }
  1877. // therefore we are skipping the start element, but by passing XmlRootAttribute with the same name as
  1878. // we open the start element (column's name), XmlSerializer will open and close it for us
  1879. XmlRootAttribute xmlAttrib = new XmlRootAttribute(col.EncodedColumnName);
  1880. xmlAttrib.Namespace = col.Namespace;
  1881. col.ConvertObjectToXml(columnValue, _xmlw, xmlAttrib);
  1882. }
  1883. }
  1884. else { // value is built in CLR type (eg: string, int etc.)
  1885. // these basic clr types do not have direct xsd type mappings
  1886. if (valuesType == typeof(Type) || valuesType == typeof(Guid)|| valuesType == typeof(Char) ||
  1887. DataStorage.IsSqlType(valuesType) ) { // if unmapped type or SQL type write msdata:Datatype=typeofinstance
  1888. _xmlw.WriteAttributeString(Keywords.MSD, Keywords.MSD_INSTANCETYPE, Keywords.MSDNS, valuesType.FullName);
  1889. }
  1890. else if (columnValue is Type) {
  1891. _xmlw.WriteAttributeString(Keywords.MSD, Keywords.MSD_INSTANCETYPE, Keywords.MSDNS, Keywords.TYPEINSTANCE);
  1892. }
  1893. else {
  1894. string xsdTypeName = Keywords.XSD_PREFIXCOLON+ XmlTreeGen.XmlDataTypeName(valuesType);
  1895. _xmlw.WriteAttributeString(Keywords.XSI, Keywords.TYPE, Keywords.XSINS, xsdTypeName);
  1896. _xmlw.WriteAttributeString (Keywords.XMLNS_XSD, Keywords.XSDNS);
  1897. }
  1898. if (!DataStorage.IsSqlType(valuesType)) {
  1899. _xmlw.WriteString(col.ConvertObjectToXml(columnValue));
  1900. }
  1901. else {
  1902. col.ConvertObjectToXml(columnValue, _xmlw, null);
  1903. }
  1904. }
  1905. }
  1906. }
  1907. if (!startElementSkipped) {
  1908. _xmlw.WriteEndElement();
  1909. }
  1910. break;
  1911. }
  1912. }
  1913. internal static string QualifiedName(string prefix, string name) {
  1914. if (prefix != null)
  1915. return prefix + ":" + name;
  1916. return name;
  1917. }
  1918. }
  1919. // DataTreeWriter
  1920. internal sealed class XmlDataTreeWriter {
  1921. XmlWriter _xmlw;
  1922. DataSet _ds = null;
  1923. DataTable _dt=null;
  1924. ArrayList _dTables = new ArrayList();
  1925. DataTable [] topLevelTables;
  1926. bool fFromTable = false; // also means no hierarchy
  1927. bool isDiffgram = false;
  1928. Hashtable rowsOrder = null;
  1929. bool _writeHierarchy = false;
  1930. internal XmlDataTreeWriter(DataSet ds) {
  1931. _ds = ds;
  1932. topLevelTables = ds.TopLevelTables();
  1933. foreach(DataTable table in ds.Tables) {
  1934. _dTables.Add(table);
  1935. }
  1936. }
  1937. internal XmlDataTreeWriter(DataSet ds, DataTable dt) { // need to modify this also
  1938. _ds = ds;
  1939. _dt = dt;
  1940. _dTables.Add(dt);
  1941. topLevelTables = ds.TopLevelTables();
  1942. }
  1943. internal XmlDataTreeWriter(DataTable dt, bool writeHierarchy) {
  1944. _dt = dt;
  1945. fFromTable = true;
  1946. if (dt.DataSet == null) {
  1947. _dTables.Add(dt);
  1948. topLevelTables = new DataTable[] {dt};
  1949. }
  1950. else {
  1951. _ds = dt.DataSet;
  1952. _dTables.Add(dt);
  1953. if (writeHierarchy) {
  1954. this._writeHierarchy = true;
  1955. CreateTablesHierarchy(dt);
  1956. topLevelTables = CreateToplevelTables();
  1957. }
  1958. else // if no hierarchy , top level table should be dt
  1959. topLevelTables = new DataTable[] {dt};
  1960. }
  1961. }
  1962. private DataTable[] CreateToplevelTables() {
  1963. ArrayList topTables = new ArrayList();
  1964. for (int i = 0; i < _dTables.Count; i++) {
  1965. DataTable table =(DataTable) _dTables[i];
  1966. if (table.ParentRelations.Count == 0)
  1967. topTables.Add(table);
  1968. else {
  1969. bool fNestedButNotSelfNested = false;
  1970. for (int j = 0; j < table.ParentRelations.Count; j++) {
  1971. if (table.ParentRelations[j].Nested) {
  1972. if (table.ParentRelations[j].ParentTable == table) {
  1973. fNestedButNotSelfNested = false;
  1974. break;
  1975. }
  1976. fNestedButNotSelfNested = true;
  1977. }
  1978. }
  1979. if (!fNestedButNotSelfNested)
  1980. topTables.Add(table);
  1981. }
  1982. }
  1983. if (topTables.Count == 0)
  1984. return (new DataTable[0]);
  1985. DataTable[] temp = new DataTable[topTables.Count];
  1986. topTables.CopyTo(temp, 0);
  1987. return temp;
  1988. }
  1989. private void CreateTablesHierarchy(DataTable dt) {
  1990. // if (!dt.SerializeHierarchy)
  1991. // return;
  1992. foreach( DataRelation r in dt.ChildRelations ) {
  1993. if (! _dTables.Contains((DataTable)r.ChildTable)) {
  1994. _dTables.Add((DataTable)r.ChildTable);
  1995. CreateTablesHierarchy(r.ChildTable) ;
  1996. }
  1997. }
  1998. }
  1999. internal static bool RowHasErrors(DataRow row) {
  2000. int colCount = row.Table.Columns.Count;
  2001. if ((row.HasErrors) && (row.RowError.Length > 0))
  2002. return true;
  2003. for (int colNum = 0; colNum < colCount; ++colNum) {
  2004. DataColumn column = row.Table.Columns[colNum];
  2005. string error = row.GetColumnError(column);
  2006. if (error == null || error.Length == 0) {
  2007. continue;
  2008. }
  2009. return true;
  2010. }
  2011. return false;
  2012. }
  2013. // the following line writes the data part
  2014. // for the new diffgram format
  2015. internal void SaveDiffgramData(XmlWriter xw, Hashtable rowsOrder) {
  2016. _xmlw = DataTextWriter.CreateWriter(xw);
  2017. isDiffgram = true;
  2018. this.rowsOrder = rowsOrder;
  2019. int countTopTable = topLevelTables.Length;
  2020. string prefix = (_ds!= null)?(( _ds.Namespace.Length == 0 )? "" : _ds.Prefix):(( _dt.Namespace.Length == 0 )? "" : _dt.Prefix);
  2021. if (_ds == null || _ds.DataSetName == null || _ds.DataSetName.Length == 0)
  2022. _xmlw.WriteStartElement(prefix, Keywords.DOCUMENTELEMENT, ( _dt.Namespace == null) ? "":_dt.Namespace);
  2023. else
  2024. _xmlw.WriteStartElement(prefix, XmlConvert.EncodeLocalName(_ds.DataSetName), _ds.Namespace);
  2025. // new XmlTreeGen(true).Save(_ds,_xmlw, false /* we don't care since we specified it's serialized */);
  2026. for(int i = 0; i < _dTables.Count ; i++) {
  2027. DataTable tempTable = ((DataTable)_dTables[i]);
  2028. foreach (DataRow row in tempTable.Rows) {
  2029. if (row.RowState == DataRowState.Deleted)
  2030. continue;
  2031. int nestedParentRowCount = row.GetNestedParentCount();
  2032. if (nestedParentRowCount == 0) {
  2033. DataTable tempDT = ((DataTable)_dTables[i]);
  2034. XmlDataRowWriter(row,tempDT.EncodedTableName);
  2035. }
  2036. else if (nestedParentRowCount > 1){
  2037. throw ExceptionBuilder.MultipleParentRows(tempTable.Namespace.Length == 0 ? tempTable.TableName:tempTable.Namespace + tempTable.TableName);
  2038. // At all times a nested row can only have 0 or 1 parents, never more than 1
  2039. }
  2040. }
  2041. }
  2042. _xmlw.WriteEndElement();
  2043. _xmlw.Flush();
  2044. }
  2045. internal void Save(XmlWriter xw, bool writeSchema) {
  2046. _xmlw = DataTextWriter.CreateWriter(xw);
  2047. int countTopTable = topLevelTables.Length;
  2048. bool fWriteDSElement = true;
  2049. string prefix = (_ds!= null)?(( _ds.Namespace.Length == 0 )? "" : _ds.Prefix):(( _dt.Namespace.Length == 0 )? "" : _dt.Prefix);
  2050. if (!writeSchema && _ds != null && _ds.fTopLevelTable && countTopTable == 1) {
  2051. if (_ds.TopLevelTables()[0].Rows.Count == 1)
  2052. fWriteDSElement = false;
  2053. }
  2054. if (fWriteDSElement) {
  2055. if (_ds == null) {
  2056. _xmlw.WriteStartElement(prefix, Keywords.DOCUMENTELEMENT, _dt.Namespace);
  2057. }
  2058. else {
  2059. if (_ds.DataSetName == null || _ds.DataSetName.Length == 0)
  2060. _xmlw.WriteStartElement(prefix, Keywords.DOCUMENTELEMENT, _ds.Namespace);
  2061. else
  2062. _xmlw.WriteStartElement(prefix, XmlConvert.EncodeLocalName(_ds.DataSetName), _ds.Namespace);
  2063. }
  2064. for(int i = 0; i < _dTables.Count ; i++) {
  2065. if (((DataTable)_dTables[i]).xmlText != null) {
  2066. _xmlw.WriteAttributeString(Keywords.XMLNS, Keywords.XSI, Keywords.XSD_XMLNS_NS, Keywords.XSINS);
  2067. break;
  2068. }
  2069. }
  2070. if (writeSchema) {
  2071. if (!fFromTable) {
  2072. new XmlTreeGen(SchemaFormat.Public).Save(_ds,_xmlw);
  2073. }
  2074. else {
  2075. new XmlTreeGen(SchemaFormat.Public).Save( null, _dt, _xmlw, this._writeHierarchy);
  2076. }
  2077. }
  2078. }
  2079. for(int i = 0; i < _dTables.Count ; i++) {
  2080. foreach (DataRow row in ((DataTable)_dTables[i]).Rows) {
  2081. if (row.RowState == DataRowState.Deleted)
  2082. continue;
  2083. int parentRowCount = row.GetNestedParentCount();
  2084. if (parentRowCount == 0) {
  2085. XmlDataRowWriter(row, ((DataTable)_dTables[i]).EncodedTableName);
  2086. }
  2087. else if (parentRowCount > 1) {
  2088. DataTable dt = (DataTable)_dTables[i];
  2089. throw ExceptionBuilder.MultipleParentRows(dt.Namespace.Length == 0 ? dt.TableName : (dt.Namespace + dt.TableName));
  2090. // At all times a nested row can only have 0 or 1 parents, never more than 1
  2091. }
  2092. }
  2093. }
  2094. if (fWriteDSElement)
  2095. _xmlw.WriteEndElement();
  2096. _xmlw.Flush();
  2097. }
  2098. private ArrayList GetNestedChildRelations(DataRow row) {
  2099. ArrayList list = new ArrayList();
  2100. foreach( DataRelation r in row.Table.ChildRelations ) {
  2101. if (r.Nested)
  2102. list.Add(r);
  2103. }
  2104. return list;
  2105. }
  2106. internal void XmlDataRowWriter(DataRow row, String encodedTableName) {
  2107. object value;
  2108. string prefix = (row.Table.Namespace.Length == 0) ? "" : row.Table.Prefix;
  2109. _xmlw.WriteStartElement(prefix, encodedTableName, row.Table.Namespace);
  2110. if (isDiffgram) {
  2111. _xmlw.WriteAttributeString( Keywords.DFF, Keywords.DIFFID, Keywords.DFFNS, row.Table.TableName+row.rowID.ToString(CultureInfo.InvariantCulture));
  2112. _xmlw.WriteAttributeString( Keywords.MSD, Keywords.ROWORDER, Keywords.MSDNS, rowsOrder[row].ToString());
  2113. if (row.RowState == DataRowState.Added) {
  2114. _xmlw.WriteAttributeString( Keywords.DFF, Keywords.HASCHANGES, Keywords.DFFNS, Keywords.INSERTED);
  2115. }
  2116. if (row.RowState == DataRowState.Modified) {
  2117. _xmlw.WriteAttributeString( Keywords.DFF, Keywords.HASCHANGES, Keywords.DFFNS, Keywords.MODIFIED);
  2118. }
  2119. if (RowHasErrors(row)) {
  2120. _xmlw.WriteAttributeString( Keywords.DFF, Keywords.HASERRORS, Keywords.DFFNS, Keywords.TRUE);
  2121. }
  2122. }
  2123. //write the attribute columns first, if any
  2124. foreach( DataColumn col in row.Table.Columns )
  2125. {
  2126. if (col.columnMapping == MappingType.Attribute)
  2127. {
  2128. value = row[col];
  2129. string colPrefix = (col.Namespace.Length == 0) ? "" : col.Prefix;
  2130. if ((value != DBNull.Value) && (!col.ImplementsINullable || !DataStorage.IsObjectSqlNull(value))){
  2131. XmlTreeGen.ValidateColumnMapping(col.DataType);
  2132. _xmlw.WriteAttributeString(colPrefix, col.EncodedColumnName, col.Namespace, col.ConvertObjectToXml(value));
  2133. }
  2134. }
  2135. if (!isDiffgram)
  2136. continue;
  2137. if (col.columnMapping == MappingType.Hidden)
  2138. {
  2139. value = row[col];
  2140. if ((value != DBNull.Value) && (!col.ImplementsINullable || !DataStorage.IsObjectSqlNull(value))){
  2141. XmlTreeGen.ValidateColumnMapping(col.DataType);
  2142. _xmlw.WriteAttributeString(Keywords.MSD, "hidden"+col.EncodedColumnName, Keywords.MSDNS, col.ConvertObjectToXml(value));
  2143. }
  2144. }
  2145. } //end foreach
  2146. foreach( DataColumn col in row.Table.Columns )
  2147. {
  2148. if (col.columnMapping != MappingType.Hidden)
  2149. {
  2150. value = row[col];
  2151. string colPrefix = (col.Namespace.Length == 0) ? "" : col.Prefix;
  2152. bool startElementSkipped = true;
  2153. if (((value == DBNull.Value) || (col.ImplementsINullable && DataStorage.IsObjectSqlNull(value))) && (col.ColumnMapping == MappingType.SimpleContent))
  2154. _xmlw.WriteAttributeString(Keywords.XSI, Keywords.XSI_NIL, Keywords.XSINS, Keywords.TRUE);
  2155. // basically this is a continue; if it is null we write xsi:nil='true'
  2156. // below, the check is if it is not null
  2157. if (((value != DBNull.Value) && (!col.ImplementsINullable || !DataStorage.IsObjectSqlNull(value)))&&(col.columnMapping != MappingType.Attribute)){
  2158. if (col.columnMapping != MappingType.SimpleContent) {
  2159. // again, if we need to use XmlSerializer, do not write start Element (see above for more info)
  2160. if (!col.IsCustomType || !col.IsValueCustomTypeInstance(value) ||(typeof(IXmlSerializable).IsAssignableFrom(value.GetType()))) {
  2161. _xmlw.WriteStartElement(colPrefix, col.EncodedColumnName, col.Namespace);
  2162. startElementSkipped = false;
  2163. }
  2164. }
  2165. Type valuesType = value.GetType();
  2166. if (!col.IsCustomType) { // if column's type is built in type: CLR and SQLTypes : ie storage supported types
  2167. if(valuesType == typeof(char) || valuesType == typeof(string)) {
  2168. if (PreserveSpace(value)) {
  2169. _xmlw.WriteAttributeString(Keywords.XML, Keywords.SPACE, Keywords.XML_XMLNS, Keywords.PRESERVE);
  2170. }
  2171. }
  2172. _xmlw.WriteString(col.ConvertObjectToXml(value));
  2173. }
  2174. else { // Columns type is CDT
  2175. if (col.IsValueCustomTypeInstance(value) /*&& !(value is Type) && valuesType != typeof(Type)*/) {// value is also CDT
  2176. // if SkippedElement, ie does not implement IXMLSerializable: so No Polymorphism Support.
  2177. if (!startElementSkipped && valuesType != col.DataType) { // for polymorphism.
  2178. _xmlw.WriteAttributeString(Keywords.MSD, Keywords.MSD_INSTANCETYPE, Keywords.MSDNS, DataStorage.GetQualifiedName(valuesType));
  2179. }
  2180. if (!startElementSkipped) { // make sure XmlRootAttribute is passed null as this type implement IXmlSerializable
  2181. col.ConvertObjectToXml(value, _xmlw, null); // pass XmlRootAttribute as null, it also means: No XmlSerializer
  2182. }
  2183. else{ // startElement is skipped: this guy does not implement IXmlSerializable, need to go via XmlSerializer
  2184. if (value.GetType() != col.DataType) { // throw if polymorphism; not supported
  2185. throw ExceptionBuilder.PolymorphismNotSupported(valuesType.AssemblyQualifiedName);
  2186. }
  2187. // therefore we are skipping the start element, but by passing XmlRootAttribute with the same name as
  2188. // we open the start element (column's name), XmlSerializer will open and close it for us
  2189. XmlRootAttribute xmlAttrib = new XmlRootAttribute(col.EncodedColumnName);
  2190. xmlAttrib.Namespace = col.Namespace;
  2191. col.ConvertObjectToXml(value, _xmlw, xmlAttrib);
  2192. }
  2193. }
  2194. else { // this is case that column type is object and value is CLR or SQLTypes
  2195. if (valuesType == typeof(Type) || valuesType == typeof(Guid)|| valuesType == typeof(Char) ||
  2196. DataStorage.IsSqlType(valuesType)) { // if unmapped type or SQL type write msdata:Datatype=typeofinstance
  2197. _xmlw.WriteAttributeString(Keywords.MSD, Keywords.MSD_INSTANCETYPE, Keywords.MSDNS, valuesType.FullName);
  2198. }
  2199. else if (value is Type) {
  2200. _xmlw.WriteAttributeString(Keywords.MSD, Keywords.MSD_INSTANCETYPE, Keywords.MSDNS, Keywords.TYPEINSTANCE);
  2201. }
  2202. else {
  2203. string xsdTypeName = Keywords.XSD_PREFIXCOLON+ XmlTreeGen.XmlDataTypeName(valuesType);
  2204. _xmlw.WriteAttributeString(Keywords.XSI, Keywords.TYPE, Keywords.XSINS, xsdTypeName);
  2205. _xmlw.WriteAttributeString (Keywords.XMLNS_XSD, Keywords.XSDNS);
  2206. }
  2207. if (!DataStorage.IsSqlType(valuesType)) {
  2208. _xmlw.WriteString(col.ConvertObjectToXml(value));
  2209. }
  2210. else {
  2211. col.ConvertObjectToXml(value, _xmlw, null);
  2212. }
  2213. }
  2214. }
  2215. if (col.columnMapping != MappingType.SimpleContent && !startElementSkipped)
  2216. _xmlw.WriteEndElement();
  2217. }
  2218. }
  2219. } //end foreach
  2220. if (_ds != null)
  2221. foreach( DataRelation dr in GetNestedChildRelations(row) ) {
  2222. foreach( DataRow r in row.GetChildRows(dr) ) {
  2223. XmlDataRowWriter(r,dr.ChildTable.EncodedTableName);
  2224. }
  2225. }
  2226. _xmlw.WriteEndElement();
  2227. }
  2228. internal static bool PreserveSpace(object value) {
  2229. Debug.Assert(value != null, "Value can not be null");
  2230. string tempValue = value.ToString();
  2231. if (tempValue.Length == 0) {
  2232. return false;
  2233. }
  2234. for(int i =0; i < tempValue.Length; i++) {
  2235. if (!Char.IsWhiteSpace(tempValue, i)) {
  2236. return false;
  2237. }
  2238. }
  2239. return true;
  2240. }
  2241. }
  2242. internal sealed class DataTextWriter : XmlWriter {
  2243. private XmlWriter _xmltextWriter;
  2244. internal static XmlWriter CreateWriter(XmlWriter xw) {
  2245. return new DataTextWriter(xw);
  2246. }
  2247. private DataTextWriter(XmlWriter w) {
  2248. _xmltextWriter = w;
  2249. }
  2250. internal Stream BaseStream {
  2251. get {
  2252. XmlTextWriter textWriter = _xmltextWriter as XmlTextWriter;
  2253. if (null != textWriter) {
  2254. return textWriter.BaseStream;
  2255. }
  2256. return null;
  2257. }
  2258. }
  2259. public override void WriteStartDocument() {
  2260. _xmltextWriter.WriteStartDocument();
  2261. }
  2262. public override void WriteStartDocument(bool standalone) {
  2263. _xmltextWriter.WriteStartDocument(standalone);
  2264. }
  2265. public override void WriteEndDocument() {
  2266. _xmltextWriter.WriteEndDocument();
  2267. }
  2268. public override void WriteDocType(string name, string pubid, string sysid, string subset) {
  2269. _xmltextWriter.WriteDocType(name, pubid, sysid, subset);
  2270. }
  2271. public override void WriteStartElement(string prefix, string localName, string ns) {
  2272. _xmltextWriter.WriteStartElement(prefix, localName, ns);
  2273. }
  2274. public override void WriteEndElement() {
  2275. _xmltextWriter.WriteEndElement();
  2276. }
  2277. public override void WriteFullEndElement() {
  2278. _xmltextWriter.WriteFullEndElement();
  2279. }
  2280. public override void WriteStartAttribute(string prefix, string localName, string ns) {
  2281. _xmltextWriter.WriteStartAttribute(prefix, localName, ns);
  2282. }
  2283. public override void WriteEndAttribute() {
  2284. _xmltextWriter.WriteEndAttribute();
  2285. }
  2286. public override void WriteCData(string text) {
  2287. _xmltextWriter.WriteCData(text);
  2288. }
  2289. public override void WriteComment(string text) {
  2290. _xmltextWriter.WriteComment(text);
  2291. }
  2292. public override void WriteProcessingInstruction(string name, string text) {
  2293. _xmltextWriter.WriteProcessingInstruction(name, text);
  2294. }
  2295. public override void WriteEntityRef(string name) {
  2296. _xmltextWriter.WriteEntityRef(name);
  2297. }
  2298. public override void WriteCharEntity(char ch) {
  2299. _xmltextWriter.WriteCharEntity(ch);
  2300. }
  2301. public override void WriteWhitespace(string ws) {
  2302. _xmltextWriter.WriteWhitespace(ws);
  2303. }
  2304. public override void WriteString(string text) {
  2305. _xmltextWriter.WriteString(text);
  2306. }
  2307. public override void WriteSurrogateCharEntity(char lowChar, char highChar){
  2308. _xmltextWriter.WriteSurrogateCharEntity(lowChar, highChar);
  2309. }
  2310. public override void WriteChars(Char[] buffer, int index, int count) {
  2311. _xmltextWriter.WriteChars(buffer, index, count);
  2312. }
  2313. public override void WriteRaw(Char[] buffer, int index, int count) {
  2314. _xmltextWriter.WriteRaw(buffer, index, count);
  2315. }
  2316. public override void WriteRaw(String data) {
  2317. _xmltextWriter.WriteRaw(data);
  2318. }
  2319. public override void WriteBase64(byte[] buffer, int index, int count) {
  2320. _xmltextWriter.WriteBase64(buffer, index, count);
  2321. }
  2322. public override void WriteBinHex( byte[] buffer, int index, int count ) {
  2323. _xmltextWriter.WriteBinHex(buffer, index, count);
  2324. }
  2325. public override WriteState WriteState {
  2326. get {
  2327. return _xmltextWriter.WriteState;
  2328. }
  2329. }
  2330. public override void Close() {
  2331. _xmltextWriter.Close();
  2332. }
  2333. public override void Flush() {
  2334. _xmltextWriter.Flush();
  2335. }
  2336. public override void WriteName(string name) {
  2337. _xmltextWriter.WriteName(name);
  2338. }
  2339. public override void WriteQualifiedName(string localName, string ns) {
  2340. _xmltextWriter.WriteQualifiedName(localName, ns);
  2341. }
  2342. public override string LookupPrefix(string ns) {
  2343. return _xmltextWriter.LookupPrefix(ns);
  2344. }
  2345. public override XmlSpace XmlSpace {
  2346. get {
  2347. return _xmltextWriter.XmlSpace;
  2348. }
  2349. }
  2350. public override string XmlLang {
  2351. get {
  2352. return _xmltextWriter.XmlLang;
  2353. }
  2354. }
  2355. public override void WriteNmToken(string name) {
  2356. _xmltextWriter.WriteNmToken(name);
  2357. }
  2358. }
  2359. internal sealed class DataTextReader : XmlReader {
  2360. private XmlReader _xmlreader;
  2361. internal static XmlReader CreateReader(XmlReader xr) {
  2362. Debug.Assert(!(xr is DataTextReader), "XmlReader is DataTextReader");
  2363. return new DataTextReader(xr);
  2364. }
  2365. private DataTextReader( XmlReader input ) {
  2366. _xmlreader = input;
  2367. }
  2368. public override XmlReaderSettings Settings {
  2369. get {
  2370. return _xmlreader.Settings;
  2371. }
  2372. }
  2373. public override XmlNodeType NodeType {
  2374. get {
  2375. return _xmlreader.NodeType;
  2376. }
  2377. }
  2378. public override string Name {
  2379. get {
  2380. return _xmlreader.Name;
  2381. }
  2382. }
  2383. public override string LocalName {
  2384. get {
  2385. return _xmlreader.LocalName;
  2386. }
  2387. }
  2388. public override string NamespaceURI {
  2389. get {
  2390. return _xmlreader.NamespaceURI;
  2391. }
  2392. }
  2393. public override string Prefix {
  2394. get { return _xmlreader.Prefix; }
  2395. }
  2396. public override bool HasValue {
  2397. get { return _xmlreader.HasValue; }
  2398. }
  2399. public override string Value {
  2400. get { return _xmlreader.Value; }
  2401. }
  2402. public override int Depth {
  2403. get { return _xmlreader.Depth; }
  2404. }
  2405. public override string BaseURI {
  2406. get { return _xmlreader.BaseURI; }
  2407. }
  2408. public override bool IsEmptyElement {
  2409. get { return _xmlreader.IsEmptyElement; }
  2410. }
  2411. public override bool IsDefault {
  2412. get { return _xmlreader.IsDefault; }
  2413. }
  2414. public override char QuoteChar {
  2415. get { return _xmlreader.QuoteChar; }
  2416. }
  2417. public override XmlSpace XmlSpace {
  2418. get { return _xmlreader.XmlSpace; }
  2419. }
  2420. public override string XmlLang {
  2421. get { return _xmlreader.XmlLang; }
  2422. }
  2423. public override int AttributeCount { get { return _xmlreader.AttributeCount; } }
  2424. public override string GetAttribute( string name ) {
  2425. return _xmlreader.GetAttribute( name );
  2426. }
  2427. public override string GetAttribute( string localName, string namespaceURI ) {
  2428. return _xmlreader.GetAttribute( localName, namespaceURI );
  2429. }
  2430. public override string GetAttribute( int i ) {
  2431. return _xmlreader.GetAttribute( i );
  2432. }
  2433. public override bool MoveToAttribute( string name ) {
  2434. return _xmlreader.MoveToAttribute( name );
  2435. }
  2436. public override bool MoveToAttribute( string localName, string namespaceURI ) {
  2437. return _xmlreader.MoveToAttribute( localName, namespaceURI );
  2438. }
  2439. public override void MoveToAttribute( int i ) {
  2440. _xmlreader.MoveToAttribute( i );
  2441. }
  2442. public override bool MoveToFirstAttribute() {
  2443. return _xmlreader.MoveToFirstAttribute();
  2444. }
  2445. public override bool MoveToNextAttribute() {
  2446. return _xmlreader.MoveToNextAttribute();
  2447. }
  2448. public override bool MoveToElement() {
  2449. return _xmlreader.MoveToElement();
  2450. }
  2451. public override bool ReadAttributeValue() {
  2452. return _xmlreader.ReadAttributeValue();
  2453. }
  2454. public override bool Read() {
  2455. return _xmlreader.Read();
  2456. }
  2457. public override bool EOF {
  2458. get { return _xmlreader.EOF; }
  2459. }
  2460. public override void Close() {
  2461. _xmlreader.Close();
  2462. }
  2463. public override ReadState ReadState {
  2464. get { return _xmlreader.ReadState; }
  2465. }
  2466. public override void Skip() {
  2467. _xmlreader.Skip();
  2468. }
  2469. public override XmlNameTable NameTable {
  2470. get { return _xmlreader.NameTable; }
  2471. }
  2472. public override String LookupNamespace( String prefix ) {
  2473. return _xmlreader.LookupNamespace(prefix);
  2474. }
  2475. public override bool CanResolveEntity {
  2476. get { return _xmlreader.CanResolveEntity;}
  2477. }
  2478. public override void ResolveEntity() {
  2479. _xmlreader.ResolveEntity();
  2480. }
  2481. public override bool CanReadBinaryContent {
  2482. get { return _xmlreader.CanReadBinaryContent ; }
  2483. }
  2484. public override int ReadContentAsBase64( byte[] buffer, int index, int count ) {
  2485. return _xmlreader.ReadContentAsBase64( buffer, index, count );
  2486. }
  2487. public override int ReadElementContentAsBase64( byte[] buffer, int index, int count ) {
  2488. return _xmlreader.ReadElementContentAsBase64( buffer, index, count );
  2489. }
  2490. public override int ReadContentAsBinHex( byte[] buffer, int index, int count ) {
  2491. return _xmlreader.ReadContentAsBinHex( buffer, index, count );
  2492. }
  2493. public override int ReadElementContentAsBinHex( byte[] buffer, int index, int count ) {
  2494. return _xmlreader.ReadElementContentAsBinHex( buffer, index, count );
  2495. }
  2496. public override bool CanReadValueChunk {
  2497. get { return _xmlreader.CanReadValueChunk ; }
  2498. }
  2499. public override string ReadString() {
  2500. return _xmlreader.ReadString();
  2501. }
  2502. }
  2503. }