public override string[] GetUsersInRole(string roleName)
        {
            SecUtility.CheckParameter(ref roleName, true, true, true, MaxTableRoleNameLength, "rolename");

            try
            {
                TableStorageDataServiceContext svc      = CreateDataServiceContext();
                DataServiceQuery <RoleRow>     queryObj = svc.CreateQuery <RoleRow>(_tableName);

                IEnumerable <RoleRow> query = from user in queryObj
                                              where user.PartitionKey.CompareTo(SecUtility.EscapedFirst(_applicationName)) >= 0 &&
                                              user.PartitionKey.CompareTo(SecUtility.NextComparisonString(SecUtility.EscapedFirst(_applicationName))) < 0 &&
                                              user.RowKey == SecUtility.Escape(roleName)
                                              select user;
                TableStorageDataServiceQuery <RoleRow> q = new TableStorageDataServiceQuery <RoleRow>(query as DataServiceQuery <RoleRow>, _tableRetry);
                IEnumerable <RoleRow> userRows           = q.ExecuteAllWithRetries();

                if (userRows == null)
                {
                    // role does not exist; we are supposed to throw an exception here
                    throw new ProviderException(string.Format(CultureInfo.InstalledUICulture, "The role {0} does not exist!", roleName));
                }
                List <RoleRow> l = new List <RoleRow>(userRows);
                if (l.Count == 0 || IsStaleRole(l, roleName))
                {
                    throw new ProviderException(string.Format(CultureInfo.InstalledUICulture, "The role {0} does not exist!", roleName));
                }
                List <string> ret = new List <string>();
                foreach (RoleRow user in l)
                {
                    if (!string.IsNullOrEmpty(user.UserName))
                    {
                        ret.Add(user.UserName);
                    }
                }
                return(ret.ToArray());
            }
            catch (InvalidOperationException e)
            {
                throw new ProviderException("Error while accessing the data store.", e);
            }
        }
        // the username to match can be in a format that varies between providers
        // for this implementation, a syntax similar to the one used in the SQL provider is applied
        // "user%" will return all users in a role that start with the string "user"
        // the % sign can only appear at the end of the usernameToMatch parameter
        // because the current version of the table storage service does not support StartsWith in LINQ queries,
        // calling this function can cause significant network trafic when '%' is used in the usernameToMach
        // parameter
        public override string[] FindUsersInRole(string roleName, string usernameToMatch)
        {
            SecUtility.CheckParameter(ref roleName, true, true, true, MaxTableRoleNameLength, "rolename");
            SecUtility.CheckParameter(ref usernameToMatch, true, true, false, Constants.MaxTableUsernameLength, "usernameToMatch");

            bool startswith = false;

            if (usernameToMatch.Contains('%'))
            {
                if (usernameToMatch.IndexOf('%') != usernameToMatch.Length - 1)
                {
                    throw new ArgumentException("The TableStorageRoleProvider only supports search strings that contain '%' as the last character!");
                }
                usernameToMatch = usernameToMatch.Substring(0, usernameToMatch.Length - 1);
                startswith      = true;
            }

            try
            {
                TableStorageDataServiceContext svc      = CreateDataServiceContext();
                DataServiceQuery <RoleRow>     queryObj = svc.CreateQuery <RoleRow>(_tableName);

                IEnumerable <RoleRow> query;

                if (startswith && string.IsNullOrEmpty(usernameToMatch))
                {
                    // get all users in the role
                    query = from userRole in queryObj
                            where userRole.PartitionKey.CompareTo(SecUtility.EscapedFirst(_applicationName)) >= 0 &&
                            userRole.PartitionKey.CompareTo(SecUtility.NextComparisonString(SecUtility.EscapedFirst(_applicationName))) < 0 &&
                            userRole.RowKey == SecUtility.Escape(roleName)
                            select userRole;
                }
                else if (startswith)
                {
                    // get all users in the role that start with the specified string (we cannot restrict the query more because StartsWith is not supported)
                    // we cannot include the username to search for in the key, because the key might e escaped
                    query = from userRole in queryObj
                            where userRole.PartitionKey.CompareTo(SecUtility.EscapedFirst(_applicationName)) >= 0 &&
                            userRole.PartitionKey.CompareTo(SecUtility.NextComparisonString(SecUtility.EscapedFirst(_applicationName))) < 0 &&
                            userRole.RowKey == SecUtility.Escape(roleName) &&
                            (userRole.UserName.CompareTo(usernameToMatch) >= 0 || userRole.UserName == string.Empty)
                            select userRole;
                }
                else
                {
                    // get a specific user
                    query = from userRole in queryObj
                            where (userRole.PartitionKey == SecUtility.CombineToKey(_applicationName, usernameToMatch) ||
                                   userRole.PartitionKey == SecUtility.CombineToKey(_applicationName, string.Empty)) &&
                            userRole.RowKey == SecUtility.Escape(roleName)
                            select userRole;
                }

                TableStorageDataServiceQuery <RoleRow> q = new TableStorageDataServiceQuery <RoleRow>(query as DataServiceQuery <RoleRow>, _tableRetry);
                IEnumerable <RoleRow> userRows           = q.ExecuteAllWithRetries();

                if (userRows == null)
                {
                    throw new ProviderException("The role does not exist!");
                }
                List <RoleRow> l = new List <RoleRow>(userRows);
                if (l.Count == 0)
                {
                    // the role does not exist
                    throw new ProviderException("The role does not exist!");
                }
                RoleRow role;
                if (IsStaleRole(l, out role))
                {
                    throw new ProviderException("The role does not exist!");
                }
                List <string> ret = new List <string>();
                foreach (RoleRow row in l)
                {
                    if (row != role)
                    {
                        if (startswith && !string.IsNullOrEmpty(usernameToMatch) && !row.UserName.StartsWith(usernameToMatch, StringComparison.Ordinal))
                        {
                            continue;
                        }
                        ret.Add(row.UserName);
                    }
                }
                return(ret.ToArray());
            }
            catch (InvalidOperationException e)
            {
                throw new ProviderException("Error while accessing the data store.", e);
            }
        }
        public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
        {
            SecUtility.CheckParameter(ref roleName, true, true, true, MaxTableRoleNameLength, "rolename");

            try
            {
                TableStorageDataServiceContext svc      = CreateDataServiceContext();
                DataServiceQuery <RoleRow>     queryObj = svc.CreateQuery <RoleRow>(_tableName);

                IEnumerable <RoleRow> query = from userRole in queryObj
                                              where userRole.PartitionKey.CompareTo(SecUtility.EscapedFirst(_applicationName)) >= 0 &&
                                              userRole.PartitionKey.CompareTo(SecUtility.NextComparisonString(SecUtility.EscapedFirst(_applicationName))) < 0 &&
                                              userRole.RowKey == SecUtility.Escape(roleName)
                                              select userRole;
                TableStorageDataServiceQuery <RoleRow> q = new TableStorageDataServiceQuery <RoleRow>(query as DataServiceQuery <RoleRow>, _tableRetry);
                IEnumerable <RoleRow> userRows           = q.ExecuteAllWithRetries();

                if (userRows == null)
                {
                    return(false);
                }
                List <RoleRow> l = new List <RoleRow>(userRows);
                if (l.Count == 0)
                {
                    // the role does not exist
                    return(false);
                }
                RoleRow role;
                if (IsStaleRole(l, out role))
                {
                    return(false);
                }
                if (l.Count > 1 && throwOnPopulatedRole)
                {
                    throw new ProviderException("Cannot delete populated role.");
                }
                svc.DeleteObject(role);
                svc.SaveChangesWithRetries();
                // lets try to remove all remaining elements in the role
                foreach (RoleRow row in l)
                {
                    if (row != role)
                    {
                        try
                        {
                            svc.DeleteObject(row);
                            svc.SaveChangesWithRetries();
                        }
                        catch (InvalidOperationException ex)
                        {
                            HttpStatusCode status;
                            if (TableStorageHelpers.EvaluateException(ex, out status) && (status == HttpStatusCode.NoContent || status == HttpStatusCode.NotFound))
                            {
                                // this element already was already deleted by another process or during a failed retry
                                // this is not a fatal error; continue deleting elements
                                Log.Write(EventKind.Warning, string.Format(CultureInfo.InstalledUICulture, "The user {0} does not exist in the role {1}.", row.UserName, row.RoleName));
                            }
                            else
                            {
                                throw new ProviderException(string.Format(CultureInfo.InstalledUICulture, "Error deleting user {0} from role {1}.", row.UserName, row.RoleName));
                            }
                        }
                    }
                }
                return(true);
            }
            catch (InvalidOperationException e)
            {
                throw new ProviderException("Error while accessing the data store.", e);
            }
        }