-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathWrappedReader.cs
306 lines (226 loc) · 14.1 KB
/
WrappedReader.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
using System;
using System.Collections;
using System.Data;
using System.Data.Common;
using System.IO;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
namespace Dapper
{
internal sealed class DisposedReader : DbDataReader
{
internal static readonly DisposedReader Instance = new DisposedReader();
private DisposedReader() { }
public override int Depth => 0;
public override int FieldCount => 0;
public override bool IsClosed => true;
public override bool HasRows => false;
public override int RecordsAffected => -1;
public override int VisibleFieldCount => 0;
[MethodImpl(MethodImplOptions.NoInlining)]
private static T ThrowDisposed<T>() => throw new ObjectDisposedException(nameof(DbDataReader));
[MethodImpl(MethodImplOptions.NoInlining)]
private async static Task<T> ThrowDisposedAsync<T>()
{
var result = ThrowDisposed<T>();
await Task.Yield(); // will never hit this - already thrown and handled
return result;
}
public override void Close() { }
public override DataTable GetSchemaTable() => ThrowDisposed<DataTable>();
#if PLAT_NO_REMOTING
[Obsolete("This Remoting API is not supported and throws PlatformNotSupportedException.", DiagnosticId = "SYSLIB0010", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")]
#endif
public override object InitializeLifetimeService() => ThrowDisposed<object>();
protected override void Dispose(bool disposing) { }
public override bool GetBoolean(int ordinal) => ThrowDisposed<bool>();
public override long GetBytes(int ordinal, long dataOffset, byte[] buffer, int bufferOffset, int length) => ThrowDisposed<long>();
public override float GetFloat(int ordinal) => ThrowDisposed<float>();
public override short GetInt16(int ordinal) => ThrowDisposed<short>();
public override byte GetByte(int ordinal) => ThrowDisposed<byte>();
public override char GetChar(int ordinal) => ThrowDisposed<char>();
public override long GetChars(int ordinal, long dataOffset, char[] buffer, int bufferOffset, int length) => ThrowDisposed<long>();
public override string GetDataTypeName(int ordinal) => ThrowDisposed<string>();
public override DateTime GetDateTime(int ordinal) => ThrowDisposed<DateTime>();
protected override DbDataReader GetDbDataReader(int ordinal) => ThrowDisposed<DbDataReader>();
public override decimal GetDecimal(int ordinal) => ThrowDisposed<decimal>();
public override double GetDouble(int ordinal) => ThrowDisposed<double>();
public override IEnumerator GetEnumerator() => ThrowDisposed<IEnumerator>();
public override Type GetFieldType(int ordinal) => ThrowDisposed<Type>();
public override T GetFieldValue<T>(int ordinal) => ThrowDisposed<T>();
public override Task<T> GetFieldValueAsync<T>(int ordinal, CancellationToken cancellationToken) => ThrowDisposedAsync<T>();
public override Guid GetGuid(int ordinal) => ThrowDisposed<Guid>();
public override int GetInt32(int ordinal) => ThrowDisposed<int>();
public override long GetInt64(int ordinal) => ThrowDisposed<long>();
public override string GetName(int ordinal) => ThrowDisposed<string>();
public override int GetOrdinal(string name) => ThrowDisposed<int>();
public override Type GetProviderSpecificFieldType(int ordinal) => ThrowDisposed<Type>();
public override object GetProviderSpecificValue(int ordinal) => ThrowDisposed<object>();
public override int GetProviderSpecificValues(object[] values) => ThrowDisposed<int>();
public override Stream GetStream(int ordinal) => ThrowDisposed<Stream>();
public override string GetString(int ordinal) => ThrowDisposed<string>();
public override TextReader GetTextReader(int ordinal) => ThrowDisposed<TextReader>();
public override object GetValue(int ordinal) => ThrowDisposed<object>();
public override int GetValues(object[] values) => ThrowDisposed<int>();
public override bool IsDBNull(int ordinal) => ThrowDisposed<bool>();
public override Task<bool> IsDBNullAsync(int ordinal, CancellationToken cancellationToken) => ThrowDisposedAsync<bool>();
public override bool NextResult() => ThrowDisposed<bool>();
public override bool Read() => ThrowDisposed<bool>();
public override Task<bool> NextResultAsync(CancellationToken cancellationToken) => ThrowDisposedAsync<bool>();
public override Task<bool> ReadAsync(CancellationToken cancellationToken) => ThrowDisposedAsync<bool>();
public override object this[int ordinal] => ThrowDisposed<object>();
public override object this[string name] => ThrowDisposed<object>();
}
internal static class WrappedReader
{
// the purpose of wrapping here is to allow closing a reader to *also* close
// the command, without having to explicitly hand the command back to the
// caller; what that actually looks like depends on what we get: if we are
// given a DbDataReader, we will surface a DbDataReader; if we are given
// a raw IDataReader, we will surface that; and if null: null
public static IDataReader Create(IDbCommand cmd, IDataReader reader)
{
if (cmd == null) return reader; // no need to wrap if no command
if (reader is DbDataReader dbr) return new DbWrappedReader(cmd, dbr);
if (reader != null) return new BasicWrappedReader(cmd, reader);
cmd.Dispose();
return null; // GIGO
}
public static DbDataReader Create(IDbCommand cmd, DbDataReader reader)
{
if (cmd == null) return reader; // no need to wrap if no command
if (reader != null) return new DbWrappedReader(cmd, reader);
cmd.Dispose();
return null; // GIGO
}
}
internal sealed class DbWrappedReader : DbDataReader, IWrappedDataReader
{
private DbDataReader _reader;
private IDbCommand _cmd;
IDataReader IWrappedDataReader.Reader => _reader;
IDbCommand IWrappedDataReader.Command => _cmd;
public DbWrappedReader(IDbCommand cmd, DbDataReader reader)
{
_cmd = cmd;
_reader = reader;
}
public override bool HasRows => _reader.HasRows;
public override void Close() => _reader.Close();
public override DataTable GetSchemaTable() => _reader.GetSchemaTable();
#if PLAT_NO_REMOTING
[Obsolete("This Remoting API is not supported and throws PlatformNotSupportedException.", DiagnosticId = "SYSLIB0010", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")]
#endif
public override object InitializeLifetimeService() => _reader.InitializeLifetimeService();
public override int Depth => _reader.Depth;
public override bool IsClosed => _reader.IsClosed;
public override bool NextResult() => _reader.NextResult();
public override bool Read() => _reader.Read();
public override int RecordsAffected => _reader.RecordsAffected;
protected override void Dispose(bool disposing)
{
if (disposing)
{
_reader.Close();
_reader.Dispose();
_reader = DisposedReader.Instance; // all future ops are no-ops
_cmd?.Dispose();
_cmd = null;
}
}
public override int FieldCount => _reader.FieldCount;
public override bool GetBoolean(int i) => _reader.GetBoolean(i);
public override byte GetByte(int i) => _reader.GetByte(i);
public override long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length) =>
_reader.GetBytes(i, fieldOffset, buffer, bufferoffset, length);
public override char GetChar(int i) => _reader.GetChar(i);
public override long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length) =>
_reader.GetChars(i, fieldoffset, buffer, bufferoffset, length);
public override string GetDataTypeName(int i) => _reader.GetDataTypeName(i);
public override DateTime GetDateTime(int i) => _reader.GetDateTime(i);
public override decimal GetDecimal(int i) => _reader.GetDecimal(i);
public override double GetDouble(int i) => _reader.GetDouble(i);
public override Type GetFieldType(int i) => _reader.GetFieldType(i);
public override float GetFloat(int i) => _reader.GetFloat(i);
public override Guid GetGuid(int i) => _reader.GetGuid(i);
public override short GetInt16(int i) => _reader.GetInt16(i);
public override int GetInt32(int i) => _reader.GetInt32(i);
public override long GetInt64(int i) => _reader.GetInt64(i);
public override string GetName(int i) => _reader.GetName(i);
public override int GetOrdinal(string name) => _reader.GetOrdinal(name);
public override string GetString(int i) => _reader.GetString(i);
public override object GetValue(int i) => _reader.GetValue(i);
public override int GetValues(object[] values) => _reader.GetValues(values);
public override bool IsDBNull(int i) => _reader.IsDBNull(i);
public override object this[string name] => _reader[name];
public override object this[int i] => _reader[i];
public override T GetFieldValue<T>(int ordinal) => _reader.GetFieldValue<T>(ordinal);
public override Task<T> GetFieldValueAsync<T>(int ordinal, CancellationToken cancellationToken) => _reader.GetFieldValueAsync<T>(ordinal, cancellationToken);
public override IEnumerator GetEnumerator() => _reader.GetEnumerator();
public override Type GetProviderSpecificFieldType(int ordinal) => _reader.GetProviderSpecificFieldType(ordinal);
public override object GetProviderSpecificValue(int ordinal) => _reader.GetProviderSpecificValue(ordinal);
public override int GetProviderSpecificValues(object[] values) => _reader.GetProviderSpecificValues(values);
public override Stream GetStream(int ordinal) => _reader.GetStream(ordinal);
public override TextReader GetTextReader(int ordinal) => _reader.GetTextReader(ordinal);
public override Task<bool> IsDBNullAsync(int ordinal, CancellationToken cancellationToken) => _reader.IsDBNullAsync(ordinal, cancellationToken);
public override Task<bool> NextResultAsync(CancellationToken cancellationToken) => _reader.NextResultAsync(cancellationToken);
public override Task<bool> ReadAsync(CancellationToken cancellationToken) => _reader.ReadAsync(cancellationToken);
public override int VisibleFieldCount => _reader.VisibleFieldCount;
protected override DbDataReader GetDbDataReader(int ordinal) => (((IDataReader)_reader).GetData(ordinal) as DbDataReader) ?? throw new NotSupportedException();
}
internal class BasicWrappedReader : IWrappedDataReader
{
private IDataReader _reader;
private IDbCommand _cmd;
IDataReader IWrappedDataReader.Reader => _reader;
IDbCommand IWrappedDataReader.Command => _cmd;
public BasicWrappedReader(IDbCommand cmd, IDataReader reader)
{
_cmd = cmd;
_reader = reader;
}
void IDataReader.Close() => _reader.Close();
int IDataReader.Depth => _reader.Depth;
DataTable IDataReader.GetSchemaTable() => _reader.GetSchemaTable();
bool IDataReader.IsClosed => _reader.IsClosed;
bool IDataReader.NextResult() => _reader.NextResult();
bool IDataReader.Read() => _reader.Read();
int IDataReader.RecordsAffected => _reader.RecordsAffected;
void IDisposable.Dispose()
{
_reader.Close();
_reader.Dispose();
_reader = DisposedReader.Instance;
_cmd?.Dispose();
_cmd = null;
}
int IDataRecord.FieldCount => _reader.FieldCount;
bool IDataRecord.GetBoolean(int i) => _reader.GetBoolean(i);
byte IDataRecord.GetByte(int i) => _reader.GetByte(i);
long IDataRecord.GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length) =>
_reader.GetBytes(i, fieldOffset, buffer, bufferoffset, length);
char IDataRecord.GetChar(int i) => _reader.GetChar(i);
long IDataRecord.GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length) =>
_reader.GetChars(i, fieldoffset, buffer, bufferoffset, length);
IDataReader IDataRecord.GetData(int i) => _reader.GetData(i);
string IDataRecord.GetDataTypeName(int i) => _reader.GetDataTypeName(i);
DateTime IDataRecord.GetDateTime(int i) => _reader.GetDateTime(i);
decimal IDataRecord.GetDecimal(int i) => _reader.GetDecimal(i);
double IDataRecord.GetDouble(int i) => _reader.GetDouble(i);
Type IDataRecord.GetFieldType(int i) => _reader.GetFieldType(i);
float IDataRecord.GetFloat(int i) => _reader.GetFloat(i);
Guid IDataRecord.GetGuid(int i) => _reader.GetGuid(i);
short IDataRecord.GetInt16(int i) => _reader.GetInt16(i);
int IDataRecord.GetInt32(int i) => _reader.GetInt32(i);
long IDataRecord.GetInt64(int i) => _reader.GetInt64(i);
string IDataRecord.GetName(int i) => _reader.GetName(i);
int IDataRecord.GetOrdinal(string name) => _reader.GetOrdinal(name);
string IDataRecord.GetString(int i) => _reader.GetString(i);
object IDataRecord.GetValue(int i) => _reader.GetValue(i);
int IDataRecord.GetValues(object[] values) => _reader.GetValues(values);
bool IDataRecord.IsDBNull(int i) => _reader.IsDBNull(i);
object IDataRecord.this[string name] => _reader[name];
object IDataRecord.this[int i] => _reader[i];
}
}