/// <summary>
        /// Decrypts the symmetric key and saves it in metadata.
        /// </summary>
        internal static void DecryptSymmetricKey(SqlTceCipherInfoEntry sqlTceCipherInfoEntry, out SqlClientSymmetricKey sqlClientSymmetricKey, out SqlEncryptionKeyInfo encryptionkeyInfoChosen, SqlConnection connection, SqlCommand command)
        {
            Debug.Assert(sqlTceCipherInfoEntry is not null, "sqlTceCipherInfoEntry should not be null in DecryptSymmetricKey.");
            Debug.Assert(sqlTceCipherInfoEntry.ColumnEncryptionKeyValues is not null,
                         "sqlTceCipherInfoEntry.ColumnEncryptionKeyValues should not be null in DecryptSymmetricKey.");

            sqlClientSymmetricKey   = null;
            encryptionkeyInfoChosen = null;
            Exception            lastException  = null;
            SqlSymmetricKeyCache globalCekCache = SqlSymmetricKeyCache.GetInstance();

            foreach (SqlEncryptionKeyInfo keyInfo in sqlTceCipherInfoEntry.ColumnEncryptionKeyValues)
            {
                try
                {
                    sqlClientSymmetricKey = ShouldUseInstanceLevelProviderFlow(keyInfo.keyStoreName, connection, command) ?
                                            GetKeyFromLocalProviders(keyInfo, connection, command) :
                                            globalCekCache.GetKey(keyInfo, connection, command);
                    encryptionkeyInfoChosen = keyInfo;
                    break;
                }
                catch (Exception e)
                {
                    lastException = e;
                }
            }

            if (sqlClientSymmetricKey is null)
            {
                Debug.Assert(lastException is not null, "CEK decryption failed without raising exceptions");
                throw lastException;
            }

            Debug.Assert(encryptionkeyInfoChosen is not null, "encryptionkeyInfoChosen must have a value.");
        }
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="sqlTceCipherInfoEntry"></param>
        /// <param name="ordinal"></param>
        /// <param name="cipherAlgorithmId"></param>
        /// <param name="cipherAlgorithmName"></param>
        /// <param name="encryptionType"></param>
        /// <param name="normalizationRuleVersion"></param>
        internal SqlCipherMetadata(SqlTceCipherInfoEntry sqlTceCipherInfoEntry,
                                   ushort ordinal,
                                   byte cipherAlgorithmId,
                                   string cipherAlgorithmName,
                                   byte encryptionType,
                                   byte normalizationRuleVersion)
        {
            Debug.Assert(!sqlTceCipherInfoEntry.Equals(default(SqlTceCipherInfoEntry)), "sqlTceCipherInfoEntry should not be un-initialized.");

            _sqlTceCipherInfoEntry = sqlTceCipherInfoEntry;
            _ordinal                  = ordinal;
            _cipherAlgorithmId        = cipherAlgorithmId;
            _cipherAlgorithmName      = cipherAlgorithmName;
            _encryptionType           = encryptionType;
            _normalizationRuleVersion = normalizationRuleVersion;
            _sqlEncryptionKeyInfo     = null;
        }