SqlSequentialStreamSmi.cs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. using System;
  2. using System.Data.Common;
  3. using Microsoft.SqlServer.Server;
  4. namespace System.Data.SqlClient
  5. {
  6. sealed internal class SqlSequentialStreamSmi : System.IO.Stream
  7. {
  8. private SmiEventSink_Default _sink;
  9. private ITypedGettersV3 _getters;
  10. private int _columnIndex; // The index of out column in the table
  11. private long _position; // Current position in the stream
  12. private long _length; // Total length of the stream
  13. internal SqlSequentialStreamSmi(SmiEventSink_Default sink, ITypedGettersV3 getters, int columnIndex, long length)
  14. {
  15. _sink = sink;
  16. _getters = getters;
  17. _columnIndex = columnIndex;
  18. _length = length;
  19. _position = 0;
  20. }
  21. public override bool CanRead
  22. {
  23. get { return ((_sink != null) && (_getters != null)); }
  24. }
  25. public override bool CanSeek
  26. {
  27. get { return false; }
  28. }
  29. public override bool CanWrite
  30. {
  31. get { return false; }
  32. }
  33. public override void Flush()
  34. { }
  35. public override long Length
  36. {
  37. get { throw ADP.NotSupported(); }
  38. }
  39. public override long Position
  40. {
  41. get { throw ADP.NotSupported(); }
  42. set { throw ADP.NotSupported(); }
  43. }
  44. internal int ColumnIndex
  45. {
  46. get { return _columnIndex; }
  47. }
  48. public override int Read(byte[] buffer, int offset, int count)
  49. {
  50. SqlSequentialStream.ValidateReadParameters(buffer, offset, count);
  51. if (!CanRead)
  52. {
  53. throw ADP.ObjectDisposed(this);
  54. }
  55. try
  56. {
  57. // Read whichever is less: however much the user asked for, or however much we have
  58. // NOTE: It is safe to do this since count <= Int32.MaxValue, therefore the Math.Min should always result in an int
  59. int bytesNeeded = (int)Math.Min((long)count, _length - _position);
  60. int bytesRead = 0;
  61. if (bytesNeeded > 0)
  62. {
  63. bytesRead = ValueUtilsSmi.GetBytes_Unchecked(_sink, _getters, _columnIndex, _position, buffer, offset, bytesNeeded);
  64. _position += bytesRead;
  65. }
  66. return bytesRead;
  67. }
  68. catch (SqlException ex)
  69. {
  70. // Stream.Read() can't throw a SqlException - so wrap it in an IOException
  71. throw ADP.ErrorReadingFromStream(ex);
  72. }
  73. }
  74. public override long Seek(long offset, IO.SeekOrigin origin)
  75. {
  76. throw ADP.NotSupported();
  77. }
  78. public override void SetLength(long value)
  79. {
  80. throw ADP.NotSupported();
  81. }
  82. public override void Write(byte[] buffer, int offset, int count)
  83. {
  84. throw ADP.NotSupported();
  85. }
  86. /// <summary>
  87. /// Forces the stream to act as if it was closed (i.e. CanRead=false and Read() throws)
  88. /// This does not actually close the stream, read off the rest of the data or dispose this
  89. /// </summary>
  90. internal void SetClosed()
  91. {
  92. _sink = null;
  93. _getters = null;
  94. }
  95. protected override void Dispose(bool disposing)
  96. {
  97. if (disposing)
  98. {
  99. SetClosed();
  100. }
  101. base.Dispose(disposing);
  102. }
  103. }
  104. }