public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context,
                                                                          SettingsPropertyCollection collection)
        {
            if (collection == null)
            {
                throw new ArgumentNullException("collection");
            }
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            SettingsPropertyValueCollection settings = new SettingsPropertyValueCollection();

            // Do nothing if there are no properties to retrieve
            if (collection.Count < 1)
            {
                return(settings);
            }

            // For properties lacking an explicit SerializeAs setting, set
            // SerializeAs to String for strings and primitives, and XML
            // for everything else
            foreach (SettingsProperty property in collection)
            {
                if (property.SerializeAs == SettingsSerializeAs.ProviderSpecific)
                {
                    if (property.PropertyType.IsPrimitive || property.PropertyType == typeof(String))
                    {
                        property.SerializeAs = SettingsSerializeAs.String;
                    }
                    else
                    {
                        property.SerializeAs = SettingsSerializeAs.Xml;
                    }
                }
                settings.Add(new SettingsPropertyValue(property));
            }

            // Get the user name or anonymous user ID
            string username = (string)context["UserName"];

            if (string.IsNullOrEmpty(username))
            {
                return(settings);
            }

            if (!VerifyUsername(ref username))
            {
                return(settings);
            }

            MembershipRow profile = null;

            if (!DoesProfileExistAndUpdateUser(username, out profile))
            {
                // the profile does not exist
                // we update the last activity time of the user only if the profile does exist
                // so we can just return here
                return(settings);
            }

            Debug.Assert(profile != null);

            // We are ready to go: load the profile
            // Note that we do not have to deal with write locks here because we use a
            // different blob name each time we write a new profile
            StreamReader      reader = null;
            MemoryStream      stream = null;
            sqlBlobProperties blobProperties;

            string[] names;
            string   values;

            byte[] buf = null;
            string line;

            try
            {
                // Open the blob containing the profile data
                stream = new MemoryStream();
                if (!_blobProvider.GetBlobContentsWithoutInitialization(profile.ProfileBlobName, stream, out blobProperties) || blobProperties.Length == 0)
                {
                    // not an error if the blob does not exist
                    return(settings);
                }
                stream.Seek(0, SeekOrigin.Begin);
                reader = new StreamReader(stream);

                // Read names, values, and buf from the blob
                line   = reader.ReadLine();
                names  = line.Split(':');
                values = reader.ReadLine();
                if (!string.IsNullOrEmpty(values))
                {
                    UnicodeEncoding encoding = new UnicodeEncoding();
                    values = encoding.GetString(Convert.FromBase64String(values));
                }
                string temp = reader.ReadLine();
                if (!String.IsNullOrEmpty(temp))
                {
                    buf = Convert.FromBase64String(temp);
                }
                else
                {
                    buf = new byte[0];
                }
            }
            catch (InvalidOperationException se)
            {
                throw new ProviderException("Error accessing blob storage when getting property values!", se);
            }
            catch (Exception e)
            {
                throw new ProviderException("Error getting property values.", e);
            }
            finally
            {
                if (reader != null)
                {
                    reader.Close();
                }
                if (stream != null)
                {
                    stream.Close();
                }
            }
            // Decode names, values, and buf and initialize the
            // SettingsPropertyValueCollection returned to the caller
            DecodeProfileData(names, values, buf, settings);

            return(settings);
        }