Удалить элемент из коллекции (MembershipUserCollection) - операция перечисления может не выполняться - PullRequest
2 голосов
/ 08 марта 2011

Я использую asp.net 4, EF 4 в C #.Я использую System.Web.Security для управления пользователями в своем веб-приложении.

У меня есть коллекция пользователей в MembershipUserCollection, и мне нужно удалить некоторых пользователей во время foreach на этом сборщике.

Я полагаю, что этоневозможно удалить элемент из коллектора, когда вы зацикливаетесь.У вас есть идеи, как ее решить?

Пожалуйста, предоставьте мне образец кода, спасибо!

       MembershipUserCollection users = Membership.GetAllUsers();
        foreach (MembershipUser x in users)
        {
            if (!Roles.IsUserInRole(x.UserName, "CMS-AUTHOR"))
            {
                users.Remove(x.UserName);
            }
         }

Ошибка:

Collection was modified; enumeration operation may not execute. 

Ответы [ 6 ]

3 голосов
/ 08 марта 2011

Вы не можете изменить перечисление при его обходе - поместите пользователей для удаления в список, а затем удалите все из них, как только вы закончите перечисление:

   MembershipUserCollection users = Membership.GetAllUsers();
   List<string> usersToRemove = new List<string>();
   foreach (MembershipUser x in users)
   {
        if (!Roles.IsUserInRole(x.UserName, "CMS-AUTHOR"))
            usersToRemove.Add(x.UserName);
   }
   foreach(string userName in usersToRemove)
         users.Remove(userName);

или меньше, используя LINQ:

var usersToRemove = Membership.GetAllUsers()
                              .Where( user => !Roles.IsUserInRole(user.UserName, "CMS-AUTHOR"))
                              .ToList();
usersToRemove.ForEach( user => users.Remove(user.UserName));
1 голос
/ 08 марта 2011

Проблема заключается в том, как вы проходите коллекцию. Использование foreach обходит коллекцию как IEnumerable. При перемещении по IEnumerable у вас есть только ссылка на текущий элемент и метод для перехода к следующему элементу. Когда вы меняете содержимое перечислимого, этот процесс облажается. Всегда считайте коллекцию, которую вы проповедуете, неизменной; вы можете изменить свойства элементов, но вы не можете изменить структуру коллекции, добавляя или удаляя элементы.

Попробуйте что-то вроде этого:

MembershipUserCollection users = Membership.GetAllUsers();
MembershipUserCollection deletedUsers = new MembershipUserCollection();
    foreach (MembershipUser x in users)
    {
        if (!Roles.IsUserInRole(x.UserName, "CMS-AUTHOR"))
        {
            deletedUsers.Add(x);
        }
     }

foreach(MembershipUser delete in deletedUsers)
{
    users.Remove(delete);
}

Разница в том, что вы не меняете перечисляемую коллекцию. Вы можете сделать это проще с небольшим Linq:

MembershipUserCollection users = Membership.GetAllUsers();
//the difference is that the Select method creates a new enumerable that isolates changes to its source
foreach (MembershipUser x in users.Cast<MembershipUser>().Select(z=>!Roles.IsUserInRole(z.UserName, "CMS-AUTHOR")))
{
    users.Remove(z);
}
1 голос
/ 08 марта 2011

Вы не можете изменять коллекцию, которую вы перечисляете (очевидно).Попробуйте использовать LINQ.

users.ToList (). RemoveAll (x =>! Roles.InUserInRole (x.UserName, "CMS-AUTHOR"))

0 голосов
/ 08 марта 2011

Я нашел решение своей проблемы.Скажи мне, что ты думаешь, или если можно было бы лучше реализовать.Спасибо за ваше время.

        // Take all Users
        MembershipUserCollection users = Membership.GetAllUsers();
        // Create an empty collector for only User in Author
        MembershipUserCollection usersAuthors = new MembershipUserCollection();
        foreach (MembershipUser x in users)
        {
            if (Roles.IsUserInRole(x.UserName, "CMS-AUTHOR"))
            {
                usersAuthors.Add(x);
            }
        }
0 голосов
/ 08 марта 2011

Я бы, наверное, сделал что-то вроде:

var usersToRemove = from user in users
                    where !Roles.IsUserInRole(x.UserName, "CMS-AUTHOR")
                    select user;

foreach(var u in usersToRemove)
{
   users.Remove(u);
}
0 голосов
/ 08 марта 2011

Вы правы в том, в чем проблема: вы не можете изменить коллекцию, пока вы ее перечисляете.Это может вызвать всевозможные проблемы, если это будет разрешено.

Коллекция должна иметь метод ToList (), ToArray () или CopyTo (), который будет создавать копию коллекции.Сделайте копию и переберите ее.Затем вы можете изменить исходную коллекцию в этом цикле.

...