System.Data.SqlClient.TdsParser.TryProcessEnvChange C# (CSharp) Метод

TryProcessEnvChange() приватный Метод

private TryProcessEnvChange ( int tokenLength, System.Data.SqlClient.TdsParserStateObject stateObj, SqlEnvChange &sqlEnvChange ) : bool
tokenLength int
stateObj System.Data.SqlClient.TdsParserStateObject
sqlEnvChange SqlEnvChange
Результат bool
        private bool TryProcessEnvChange(int tokenLength, TdsParserStateObject stateObj, out SqlEnvChange[] sqlEnvChange)
        {
            // There could be multiple environment change messages following this token.
            byte byteLength;
            int processedLength = 0;
            int nvalues = 0;
            SqlEnvChange[] envarray = new SqlEnvChange[3];  // Why is this hardcoded to 3?

            sqlEnvChange = null;

            while (tokenLength > processedLength)
            {
                if (nvalues >= envarray.Length)
                {
                    // This is a rare path. Most of the time we will have 1 or 2 envchange data streams.
                    SqlEnvChange[] newenvarray = new SqlEnvChange[envarray.Length + 3];

                    for (int ii = 0; ii < envarray.Length; ii++)
                        newenvarray[ii] = envarray[ii];

                    envarray = newenvarray;
                }

                SqlEnvChange env = new SqlEnvChange();

                if (!stateObj.TryReadByte(out env.type))
                {
                    return false;
                }

                envarray[nvalues] = env;
                nvalues++;

                switch (env.type)
                {
                    case TdsEnums.ENV_DATABASE:
                    case TdsEnums.ENV_LANG:
                        if (!TryReadTwoStringFields(env, stateObj))
                        {
                            return false;
                        }
                        break;

                    case TdsEnums.ENV_CHARSET:
                        // we copied this behavior directly from luxor - see charset envchange
                        // section from sqlctokn.c
                        if (!TryReadTwoStringFields(env, stateObj))
                        {
                            return false;
                        }
                        if (env.newValue == TdsEnums.DEFAULT_ENGLISH_CODE_PAGE_STRING)
                        {
                            _defaultCodePage = TdsEnums.DEFAULT_ENGLISH_CODE_PAGE_VALUE;
                            _defaultEncoding = System.Text.Encoding.GetEncoding(_defaultCodePage);
                        }
                        else
                        {
                            Debug.Assert(env.newValue.Length > TdsEnums.CHARSET_CODE_PAGE_OFFSET, "TdsParser.ProcessEnvChange(): charset value received with length <=10");

                            string stringCodePage = env.newValue.Substring(TdsEnums.CHARSET_CODE_PAGE_OFFSET);

                            _defaultCodePage = Int32.Parse(stringCodePage, NumberStyles.Integer, CultureInfo.InvariantCulture);
                            _defaultEncoding = System.Text.Encoding.GetEncoding(_defaultCodePage);
                        }

                        break;

                    case TdsEnums.ENV_PACKETSIZE:
                        // take care of packet size right here
                        Debug.Assert(stateObj._syncOverAsync, "Should not attempt pends in a synchronous call");
                        if (!TryReadTwoStringFields(env, stateObj))
                        {
                            // Changing packet size does not support retry, should not pend"
                            throw SQL.SynchronousCallMayNotPend();
                        }
                        // Only set on physical state object - this should only occur on LoginAck prior
                        // to MARS initialization!
                        Int32 packetSize = Int32.Parse(env.newValue, NumberStyles.Integer, CultureInfo.InvariantCulture);

                        if (_physicalStateObj.SetPacketSize(packetSize))
                        {
                            // If packet size changed, we need to release our SNIPackets since
                            // those are tied to packet size of connection.
                            _physicalStateObj.ClearAllWritePackets();

                            // Update SNI ConsumerInfo value to be resulting packet size
                            UInt32 unsignedPacketSize = (UInt32)packetSize;
#if MANAGED_SNI
                            UInt32 result = SNIProxy.Singleton.SetConnectionBufferSize(_physicalStateObj.Handle, unsignedPacketSize);
#else
                            UInt32 result = SNINativeMethodWrapper.SNISetInfo(_physicalStateObj.Handle, SNINativeMethodWrapper.QTypes.SNI_QUERY_CONN_BUFSIZE, ref unsignedPacketSize);
#endif // MANAGED_SNI

                            Debug.Assert(result == TdsEnums.SNI_SUCCESS, "Unexpected failure state upon calling SNISetInfo");
                        }

                        break;

                    case TdsEnums.ENV_LOCALEID:
                        if (!TryReadTwoStringFields(env, stateObj))
                        {
                            return false;
                        }
                        _defaultLCID = Int32.Parse(env.newValue, NumberStyles.Integer, CultureInfo.InvariantCulture);
                        break;

                    case TdsEnums.ENV_COMPFLAGS:
                        if (!TryReadTwoStringFields(env, stateObj))
                        {
                            return false;
                        }
                        break;

                    case TdsEnums.ENV_COLLATION:
                        Debug.Assert(env.newLength == 5 || env.newLength == 0, "Improper length in new collation!");
                        if (!stateObj.TryReadByte(out byteLength))
                        {
                            return false;
                        }
                        env.newLength = byteLength;
                        if (env.newLength == 5)
                        {
                            if (!TryProcessCollation(stateObj, out env.newCollation))
                            {
                                return false;
                            }

                            // give the parser the new collation values in case parameters don't specify one
                            _defaultCollation = env.newCollation;
                            int newCodePage = GetCodePage(env.newCollation, stateObj);
                            if (newCodePage != _defaultCodePage)
                            {
                                _defaultCodePage = newCodePage;
                                _defaultEncoding = System.Text.Encoding.GetEncoding(_defaultCodePage);
                            }
                            _defaultLCID = env.newCollation.LCID;
                        }

                        if (!stateObj.TryReadByte(out byteLength))
                        {
                            return false;
                        }
                        env.oldLength = byteLength;
                        Debug.Assert(env.oldLength == 5 || env.oldLength == 0, "Improper length in old collation!");
                        if (env.oldLength == 5)
                        {
                            if (!TryProcessCollation(stateObj, out env.oldCollation))
                            {
                                return false;
                            }
                        }

                        env.length = 3 + env.newLength + env.oldLength;
                        break;

                    case TdsEnums.ENV_BEGINTRAN:
                    case TdsEnums.ENV_COMMITTRAN:
                    case TdsEnums.ENV_ROLLBACKTRAN:

                        if (!stateObj.TryReadByte(out byteLength))
                        {
                            return false;
                        }
                        env.newLength = byteLength;
                        Debug.Assert(env.newLength == 0 || env.newLength == 8, "Improper length for new transaction id!");

                        if (env.newLength > 0)
                        {
                            if (!stateObj.TryReadInt64(out env.newLongValue))
                            {
                                return false;
                            }
                            Debug.Assert(env.newLongValue != SqlInternalTransaction.NullTransactionId, "New transaction id is null?"); // the server guarantees that zero is an invalid transaction id.
                        }
                        else
                        {
                            env.newLongValue = SqlInternalTransaction.NullTransactionId; // the server guarantees that zero is an invalid transaction id.
                        }

                        if (!stateObj.TryReadByte(out byteLength))
                        {
                            return false;
                        }
                        env.oldLength = byteLength;
                        Debug.Assert(env.oldLength == 0 || env.oldLength == 8, "Improper length for old transaction id!");

                        if (env.oldLength > 0)
                        {
                            if (!stateObj.TryReadInt64(out env.oldLongValue))
                            {
                                return false;
                            }
                            Debug.Assert(env.oldLongValue != SqlInternalTransaction.NullTransactionId, "Old transaction id is null?"); // the server guarantees that zero is an invalid transaction id.
                        }
                        else
                        {
                            env.oldLongValue = SqlInternalTransaction.NullTransactionId; // the server guarantees that zero is an invalid transaction id.
                        }

                        // env.length includes 1 byte type token
                        env.length = 3 + env.newLength + env.oldLength;
                        break;

                    case TdsEnums.ENV_LOGSHIPNODE:
                        // env.newBinValue is secondary node, env.oldBinValue is witness node
                        // comes before LoginAck so we can't assert this
                        if (!TryReadTwoStringFields(env, stateObj))
                        {
                            return false;
                        }
                        break;

                    case TdsEnums.ENV_SPRESETCONNECTIONACK:
                        if (!TryReadTwoBinaryFields(env, stateObj))
                        {
                            return false;
                        }
                        break;

                    case TdsEnums.ENV_USERINSTANCE:
                        if (!TryReadTwoStringFields(env, stateObj))
                        {
                            return false;
                        }
                        break;

                    case TdsEnums.ENV_ROUTING:
                        ushort newLength;
                        if (!stateObj.TryReadUInt16(out newLength))
                        {
                            return false;
                        }
                        env.newLength = newLength;
                        byte protocol;
                        if (!stateObj.TryReadByte(out protocol))
                        {
                            return false;
                        }
                        ushort port;
                        if (!stateObj.TryReadUInt16(out port))
                        {
                            return false;
                        }
                        ushort serverLen;
                        if (!stateObj.TryReadUInt16(out serverLen))
                        {
                            return false;
                        }
                        string serverName;
                        if (!stateObj.TryReadString(serverLen, out serverName))
                        {
                            return false;
                        }
                        env.newRoutingInfo = new RoutingInfo(protocol, port, serverName);
                        ushort oldLength;
                        if (!stateObj.TryReadUInt16(out oldLength))
                        {
                            return false;
                        }
                        if (!stateObj.TrySkipBytes(oldLength))
                        {
                            return false;
                        }
                        env.length = env.newLength + oldLength + 5; // 5=2*sizeof(UInt16)+sizeof(byte) [token+newLength+oldLength]
                        break;

                    // ENVCHANGE tokens not supported by CoreCLR
                    case TdsEnums.ENV_ENLISTDTC:
                    case TdsEnums.ENV_DEFECTDTC:
                    case TdsEnums.ENV_TRANSACTIONENDED:
                    case TdsEnums.ENV_PROMOTETRANSACTION:
                    case TdsEnums.ENV_TRANSACTIONMANAGERADDRESS:
                        throw SQL.UnsupportedFeatureAndToken(_connHandler, ((TdsEnums.EnvChangeType)env.type).ToString());

                    default:
                        Debug.Assert(false, "Unknown environment change token: " + env.type);
                        break;
                }
                processedLength += env.length;
            }

            sqlEnvChange = envarray;
            return true;
        }
TdsParser