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