PageRenderTime 45ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/src/SqlServer/TransientDbConnection/SqlXmlReader.cs

http://hashfoosqlserver.codeplex.com
C# | 302 lines | 144 code | 35 blank | 123 comment | 4 complexity | c0f86b137b57043618560794e1d778f3 MD5 | raw file
  1. //=======================================================================================
  2. // Microsoft Windows Server AppFabric Customer Advisory Team (CAT) Best Practices Series
  3. //
  4. // This sample is supplemental to the technical guidance published on the community
  5. // blog at http://blogs.msdn.com/appfabriccat/.
  6. //
  7. //=======================================================================================
  8. // Copyright © 2010 Microsoft Corporation. All rights reserved.
  9. //
  10. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
  11. // EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
  12. // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. YOU BEAR THE RISK OF USING IT.
  13. //=======================================================================================
  14. using System;
  15. using System.Xml;
  16. using System.Data;
  17. using System.Data.SqlClient;
  18. namespace HashFoo.SqlServer.TransientDbConnection
  19. {
  20. #region Using references
  21. #endregion
  22. /// <summary>
  23. /// Provides a disposable wrapper for SQL XML data reader which synchronizes the SQL connection
  24. /// disposal with its own lifecycle.
  25. /// </summary>
  26. internal class SqlXmlReader : XmlReader
  27. {
  28. #region Private members
  29. private readonly IDbConnection connection;
  30. private readonly XmlReader innerReader;
  31. #endregion
  32. #region Constructors
  33. /// <summary>
  34. /// Initializes a new instance of a <see cref="SqlXmlReader"/> object associated with the specified SQL command.
  35. /// </summary>
  36. /// <param name="command">The associated SQL command providing access to the XML data for the reader.</param>
  37. public SqlXmlReader(SqlCommand command)
  38. {
  39. Guard.ArgumentNotNull(command, "command");
  40. this.connection = command.Connection;
  41. this.innerReader = command.ExecuteXmlReader();
  42. }
  43. /// <summary>
  44. /// Initializes a new instance of a <see cref="SqlXmlReader"/> object associated with the specified SQL connection and the original XML reader.
  45. /// </summary>
  46. /// <param name="connection">The associated SQL connection providing access to the XML data for this reader.</param>
  47. /// <param name="innerReader">The original XML reader access to the XML data for this reader.</param>
  48. public SqlXmlReader(IDbConnection connection, XmlReader innerReader)
  49. {
  50. Guard.ArgumentNotNull(connection, "connection");
  51. Guard.ArgumentNotNull(innerReader, "innerReader");
  52. this.connection = connection;
  53. this.innerReader = innerReader;
  54. }
  55. #endregion
  56. #region XmlReader implementation
  57. /// <summary>
  58. /// Closes both the original <see cref="System.Xml.XmlReader"/> as well as associated SQL connection.
  59. /// </summary>
  60. public override void Close()
  61. {
  62. if (this.innerReader != null)
  63. {
  64. this.innerReader.Close();
  65. }
  66. if (this.connection != null)
  67. {
  68. this.connection.Close();
  69. }
  70. }
  71. /// <summary>
  72. /// Returns the number of attributes on the current node.
  73. /// </summary>
  74. public override int AttributeCount
  75. {
  76. get { return this.innerReader.AttributeCount; }
  77. }
  78. /// <summary>
  79. /// Returns the base URI of the current node.
  80. /// </summary>
  81. public override string BaseURI
  82. {
  83. get { return this.innerReader.BaseURI; }
  84. }
  85. /// <summary>
  86. /// Returns the depth of the current node in the XML document.
  87. /// </summary>
  88. public override int Depth
  89. {
  90. get { return this.innerReader.Depth; }
  91. }
  92. /// <summary>
  93. /// Returns a value indicating whether the reader is positioned at the end of the stream.
  94. /// </summary>
  95. public override bool EOF
  96. {
  97. get { return this.innerReader.EOF; }
  98. }
  99. /// <summary>
  100. /// Returns the value of the attribute with the specified index.
  101. /// </summary>
  102. /// <param name="i">The index of the attribute. The index is zero-based. (The first attribute has index 0.)</param>
  103. /// <returns>The value of the specified attribute. This method does not move the reader.</returns>
  104. public override string GetAttribute(int i)
  105. {
  106. return this.innerReader.GetAttribute(i);
  107. }
  108. /// <summary>
  109. /// Returns the value of the attribute with the specified <see cref="System.Xml.XmlReader.LocalName"/> and <see cref="System.Xml.XmlReader.NamespaceURI"/>.
  110. /// </summary>
  111. /// <param name="name">The local name of the attribute.</param>
  112. /// <param name="namespaceURI">The namespace URI of the attribute.</param>
  113. /// <returns>The value of the specified attribute. If the attribute is not found or the value is <see cref="String.Empty"/>, null is returned. This method does not move the reader.</returns>
  114. public override string GetAttribute(string name, string namespaceURI)
  115. {
  116. return this.innerReader.GetAttribute(name, namespaceURI);
  117. }
  118. /// <summary>
  119. /// Returns the value of the attribute with the specified <see cref="System.Xml.XmlReader.Name"/>.
  120. /// </summary>
  121. /// <param name="name">The qualified name of the attribute.</param>
  122. /// <returns>The value of the specified attribute. If the attribute is not found or the value is <see cref="String.Empty"/>, null is returned.</returns>
  123. public override string GetAttribute(string name)
  124. {
  125. return this.innerReader.GetAttribute(name);
  126. }
  127. /// <summary>
  128. /// Returns a value indicating whether the current node can have a <see cref="System.Xml.XmlReader.Value"/>.
  129. /// </summary>
  130. public override bool HasValue
  131. {
  132. get { return this.innerReader.HasValue; }
  133. }
  134. /// <summary>
  135. /// Returns a value indicating whether the current node is an empty element.
  136. /// </summary>
  137. public override bool IsEmptyElement
  138. {
  139. get { return this.innerReader.IsEmptyElement; }
  140. }
  141. /// <summary>
  142. /// Returns the local name of the current node.
  143. /// </summary>
  144. public override string LocalName
  145. {
  146. get { return this.innerReader.LocalName; }
  147. }
  148. /// <summary>
  149. /// Resolves a namespace prefix in the current element's scope
  150. /// </summary>
  151. /// <param name="prefix">The prefix whose namespace URI you want to resolve. To match the default namespace, pass an empty string.</param>
  152. /// <returns>The namespace URI to which the prefix maps or null if no matching prefix is found.</returns>
  153. public override string LookupNamespace(string prefix)
  154. {
  155. return this.innerReader.LookupNamespace(prefix);
  156. }
  157. /// <summary>
  158. /// Moves to the attribute with the specified <see cref="System.Xml.XmlReader.LocalName"/> and <see cref="System.Xml.XmlReader.NamespaceURI"/>.
  159. /// </summary>
  160. /// <param name="name">The local name of the attribute.</param>
  161. /// <param name="ns">The namespace URI of the attribute.</param>
  162. /// <returns>True if the attribute is found; otherwise, false. If false, the reader's position does not change.</returns>
  163. public override bool MoveToAttribute(string name, string ns)
  164. {
  165. return this.innerReader.MoveToAttribute(name, ns);
  166. }
  167. /// <summary>
  168. /// Moves to the attribute with the specified <see cref="System.Xml.XmlReader.Name"/>.
  169. /// </summary>
  170. /// <param name="name">The qualified name of the attribute.</param>
  171. /// <returns>True if the attribute is found; otherwise, false. If false, the reader's position does not change.</returns>
  172. public override bool MoveToAttribute(string name)
  173. {
  174. return this.innerReader.MoveToAttribute(name);
  175. }
  176. /// <summary>
  177. /// Moves to the element that contains the current attribute node.
  178. /// </summary>
  179. /// <returns>True if the reader is positioned on an attribute (the reader moves to the element that owns the attribute); false if the reader is not positioned on an attribute (the position of the reader does not change).</returns>
  180. public override bool MoveToElement()
  181. {
  182. return this.innerReader.MoveToElement();
  183. }
  184. /// <summary>
  185. /// Moves to the first attribute.
  186. /// </summary>
  187. /// <returns>True if an attribute exists (the reader moves to the first attribute); otherwise, false (the position of the reader does not change).</returns>
  188. public override bool MoveToFirstAttribute()
  189. {
  190. return this.innerReader.MoveToFirstAttribute();
  191. }
  192. /// <summary>
  193. /// Moves to the next attribute.
  194. /// </summary>
  195. /// <returns>True if there is a next attribute; false if there are no more attributes.</returns>
  196. public override bool MoveToNextAttribute()
  197. {
  198. return this.innerReader.MoveToNextAttribute();
  199. }
  200. /// <summary>
  201. /// Returns the <see cref="System.Xml.XmlNameTable"/> associated with this implementation.
  202. /// </summary>
  203. public override XmlNameTable NameTable
  204. {
  205. get { return this.innerReader.NameTable; }
  206. }
  207. /// <summary>
  208. /// Returns the namespace URI (as defined in the W3C Namespace specification) of the node on which the reader is positioned.
  209. /// </summary>
  210. public override string NamespaceURI
  211. {
  212. get { return this.innerReader.NamespaceURI; }
  213. }
  214. /// <summary>
  215. /// Returns the type of the current node.
  216. /// </summary>
  217. public override XmlNodeType NodeType
  218. {
  219. get { return this.innerReader.NodeType; }
  220. }
  221. /// <summary>
  222. /// Returns the namespace prefix associated with the current node
  223. /// </summary>
  224. public override string Prefix
  225. {
  226. get { return this.innerReader.Prefix; }
  227. }
  228. /// <summary>
  229. /// Reads the next node from the stream.
  230. /// </summary>
  231. /// <returns>True if the next node was read successfully; false if there are no more nodes to read.</returns>
  232. public override bool Read()
  233. {
  234. return this.innerReader.Read();
  235. }
  236. /// <summary>
  237. /// Parses the attribute value into one or more Text, EntityReference, or EndEntity nodes.
  238. /// </summary>
  239. /// <returns>True if there are nodes to return, false if the reader is not positioned on an attribute node when the initial call is made or if all the attribute values have been read. An empty attribute, such as, misc="", returns true with a single node with a value of <see cref="String.Empty"/>.</returns>
  240. public override bool ReadAttributeValue()
  241. {
  242. return this.innerReader.ReadAttributeValue();
  243. }
  244. /// <summary>
  245. /// Returns the state of the reader.
  246. /// </summary>
  247. public override ReadState ReadState
  248. {
  249. get { return this.innerReader.ReadState; }
  250. }
  251. /// <summary>
  252. /// Resolves the entity reference for EntityReference nodes.
  253. /// </summary>
  254. public override void ResolveEntity()
  255. {
  256. this.innerReader.ResolveEntity();
  257. }
  258. /// <summary>
  259. /// Returns the text value of the current node.
  260. /// </summary>
  261. public override string Value
  262. {
  263. get { return this.innerReader.Value; }
  264. }
  265. #endregion
  266. }
  267. }