private void ReadParametersDataInput(RequestExecutionContext context) { var headers = context.RequestParameters; var parsed = context.ParsedRequest; var paramCount = headers.DataTypes.Length; if (headers.IsCollectionFlags.Length != BitVector.GetArrayLength(paramCount)) { throw new Exception(string.Format("BitVector for isCollection flags is broken")); } parsed.Params.Names = headers.Names; parsed.Params.DataTypes = headers.DataTypes; parsed.Params.OrdinalToLocalOrdinal = new int[headers.DataTypes.Length]; var collectionCount = 0; var valueCount = 0; for (var ordinal = 0; ordinal < paramCount; ordinal++) { var flag = BitVector.Get(headers.IsCollectionFlags, ordinal); if (flag) { parsed.Params.OrdinalToLocalOrdinal[ordinal] = collectionCount; collectionCount++; } else { parsed.Params.OrdinalToLocalOrdinal[ordinal] = valueCount; valueCount++; } } // collections are stored separately if (collectionCount > 0) { parsed.Params.InputCollections = new object[collectionCount]; } // single values are stored in an instance of DriverRowData if (valueCount > 0) { var fieldTypesForValues = new DbType[valueCount]; for (var ordinal = 0; ordinal < headers.DataTypes.Length; ordinal++) { if (!BitVector.Get(headers.IsCollectionFlags, ordinal)) { fieldTypesForValues[parsed.Params.OrdinalToLocalOrdinal[ordinal]] = headers.DataTypes[ordinal]; } } parsed.Params.InputValues = new DriverRowData(fieldTypesForValues); } parsed.Bulk.Attach(context.RequestMessage.Stream); try { using (var reader = new BinaryReader(parsed.Bulk, Encoding.UTF8, true)) { StringBuilder stringBuilder = null; var notnulls = new int[BitVector.GetArrayLength(paramCount)]; BitVector.Read(notnulls, paramCount, reader); for (var ordinal = 0; ordinal < paramCount; ordinal++) { var iscollection = BitVector.Get(headers.IsCollectionFlags, ordinal); if (BitVector.Get(notnulls, ordinal)) { var dbType = headers.DataTypes[ordinal]; if (stringBuilder == null && RowData.DeriveSystemType(dbType) == typeof(string)) { stringBuilder = new StringBuilder(); } // we have more than one destination, each storing a subset of input values // so ordinals are different from "flat" zero-to-paramCount enumeration var localOrdinal = parsed.Params.OrdinalToLocalOrdinal[ordinal]; if (iscollection) { parsed.Params.InputCollections[localOrdinal] = ReadCollection(dbType, reader, stringBuilder); } else { BitVector.Set(parsed.Params.InputValues.NotNulls, localOrdinal); ReadPrimitiveValue(parsed.Params.InputValues, localOrdinal, reader, stringBuilder); } } } } // client sets stream end marker after parameters data, make sure we read it // otherwise subsequent bulk reader may fail if (-1 != parsed.Bulk.ReadByte()) { throw new Exception("Did not find the end of parameters data block when expected"); } } finally { parsed.Bulk.Detach(); } }