/// <summary> /// Utility function to consume a single row of a reader in a random fashion after Read/ReadAsync has been invoked. /// </summary> protected virtual async Task ConsumeRowAsync(DataStressReader reader, bool sequentialAccess, CancellationToken token, Random rnd) { for (int i = 0; i < reader.FieldCount; i++) { if (rnd.Next(10) == 0) { break; // stop reading from this row } if (rnd.Next(2) == 0) { continue; // skip this field } bool hasBeenRead = false; // If the field is not null, we can optionally use streaming API if ((!await reader.IsDBNullSyncOrAsync(i, token, rnd)) && (rnd.NextBool())) { Type t = reader.GetFieldType(i); if (t == typeof(byte[])) { await ConsumeBytesAsync(reader, i, token, rnd); hasBeenRead = true; } else if (t == typeof(string)) { await ConsumeCharsAsync(reader, i, token, rnd); hasBeenRead = true; } } // If the field has not yet been read, or if it is non-sequential then we can re-read it if ((!hasBeenRead) || (!sequentialAccess)) { if (!await reader.IsDBNullSyncOrAsync(i, token, rnd)) { // Field value is not null, we can use new GetFieldValue<T> methods await reader.GetValueSyncOrAsync(i, token, rnd); } else { // Field value is null, we have to use old GetValue method reader.GetValue(i); } } // Do IsDBNull check again with 50% probability if (rnd.NextBool()) { await reader.IsDBNullSyncOrAsync(i, token, rnd); } } }
protected virtual async Task ConsumeBytesAsync(DataStressReader reader, int i, CancellationToken token, Random rnd) { byte[] buffer = new byte[255]; if (rnd.NextBool()) { // We can optionally use GetBytes reader.GetBytes(i, rnd.Next(20), buffer, rnd.Next(20), rnd.Next(200)); } else if (reader.GetName(i) != "timestamp_FLD") { // Timestamp appears to be binary, but cannot be read by Stream DataStressStream stream = reader.GetStream(i); await stream.ReadSyncOrAsync(buffer, rnd.Next(20), rnd.Next(200), token, rnd); } else { // It is timestamp column, so read it later with GetValueSyncOrAsync await reader.GetValueSyncOrAsync(i, token, rnd); } }