Beispiel #1
0
        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();
            }
        }