Исключение для Membership.GetAllUsers () после входа в систему: «Элемент уже добавлен» - PullRequest
5 голосов
/ 15 октября 2010

У меня работает два сайта, на которых работает поставщик. Одним из них является сайт ASP Playground, а другим - сайт, на котором установлен пакет интеграции сайта ASP Playground. Давайте назовем их ASPPG-сайтом и SIP-сайтом.

Иногда я получаю сообщение об ошибке при запуске Membership.GetAllUsers () на сайте SIP. Этот метод отменяется SIP, поэтому он не является стандартной версией ASP.NET.

Это происходит только иногда. Я заметил, что это происходит только тогда, когда происходит какое-то изменение в одном из участников. Затем он должен воссоздать хеш-таблицу, в которой хранятся все пользователи при вызове Membership.GetAllUsers (), и похоже, что это восстановление каким-то образом идет не так.

В исключении, которое я вставил ниже, "adminratoren" - это имя пользователя логина, в котором была изменена некоторая информация.

Не помогает принудительно выгружать сайт, обновляя web.config. Это не помогает перезапустить IIS или полностью перезагрузить сервер. После появления исключения оно продолжает появляться каждый раз, когда вызывается Membership.GetAllUsers (). Внезапно, неожиданно, исключение исчезает, и снова можно войти в систему и запустить Membership.GetAllUsers () без каких-либо исключений. Похоже, что ошибка в базе данных, и способ ее исправить - загрузить любую страницу сайта ASPPG. Затем ошибка исправляется на сайте SIP.

Что вызывает исключение и как его остановить?

Полное исключение:

Ошибка сервера в приложении '/'.
Товар уже добавлен. Ключ в словаре: «Administratoren» Добавляемый ключ: «Administratoren» Описание: во время выполнения текущего веб-запроса произошло необработанное исключение. Пожалуйста, просмотрите трассировку стека для получения дополнительной информации об ошибке и о том, где она возникла в коде.

Сведения об исключении: System.ArgumentException: элемент уже добавлен. Ключ в словаре: «Administratoren» Добавляемый ключ: «Administratoren»

Ошибка источника:

Линье 116: MembershipUserCollection allUsers;
Линье 117: блокировка (objLock) {
Линье 118: allUsers = Membership.GetAllUsers ();
Линье 119:}
Линье 120:

Исходный файл: [WebsiteLocation] \ App_Code \ MemberInfo.cs Строка: 118

Трассировка стека: (Обратите внимание, что номера строк MemberInfo.cs в этой трассировке стека могут быть немного не такими.

[ArgumentException: элемент уже добавлен. Ключ в словаре: «Administratoren» Добавляемый ключ: «Administratoren»]
System.Collections.Hashtable.Insert (ключ объекта, значение объекта, логическое добавление) + 7484392
System.Collections.Hashtable.Add (ключ объекта, значение объекта) + 11
System.Web.Security.MembershipUserCollection.Add (пользователь MembershipUser) + 129
ASPPG.MembershipProviders.ASPPGSqlMembershipProvider.CreateMembershipUserCollectionFromDataView (DataView dv) в H: \ My Document \ Visual Studio 2008 \ Projects \ forumu \ MembershipProviders \ ASPPGSqlMembershipProvider.vb: 656 ASPPG.MembershipProviders.ASPPGSqlMembershipProvider.GetAllUsers (Int32 pageIndex, Int32 pageSize, Int32 & totalRecords) в H: \ My Document \ Visual Studio 2008 \ Проекты \ forumu \ MembershipProviders \ ASPPGSqlMembershipProvider.vb 360 System.Web.Security.Membership.GetAllUsers (Int32 pageIndex, Int32 pageSize, Int32 & totalRecords) +65 System.Web.Security.Membership.GetAllUsers () +26 MemberInfo.GetAllMembers () в d: \ Faelles \ SVN-exports \ DFF-umbraco \ App_Code \ MemberInfo.cs: 71 usercontrols_GetMemberTopList.LoadTopMembers () в d: \ Faelles \ SVN-exports \ DFF-umbraco \ usercontrols \ GetMemberTopList.ascx.cs: 16 usercontrols_GetMemberTopList.Page_Load (Отправитель объекта, EventArgs e) в d: \ Faelles \ SVN-exports \ DFF-umbraco \ usercontrols \ GetMemberTopList.ascx.cs: 11 System.Web.Util.CalliHelper.EventArgFunctionCaller (IntPtr fp, Объект o, Объект t, EventArgs e) +14System.Web.Util.CalliEventHandlerDelegateProxy.Callback (Отправитель объекта, EventArgs e) +35 System.Web.UI.Control.OnLoad (EventArgs e) +99 System.Web.UI.Control.LoadRecursive () +50 System.Web.UI.Control.LoadRecursive () +141 System.Web.UI.Control.LoadRecursive () +141 System.Web.UI.Control.LoadRecursive () +141 System.Web.UI.Control.LoadRecursive () +141 System.Web.UI.Control.LoadRecursive () +141 System.Web.UI.Control.LoadRecursive () +141 System.Web.UI.Control.LoadRecursive () +141 System.Web.UI.Control.LoadRecursive () +141 System.Web.UI.Control.LoadRecursive () +141 System.Web.UI.Control.LoadRecursive () +141 System.Web.UI.Control.LoadRecursive () +141 System.Web.UI.Control.LoadRecursive () +141 System.Web.UI.Page.ProcessRequestMain (логическое значение includeStagesBeforeAsyncPoint, логическое значение includeStagesAfterAsyncPoint) + 627

Информация о версии: Microsoft .NET Framework Версия: 2.0.50727.3603; ASP.NET версия: 2.0.50727.3618

Содержимое MemberInfo.cs находится здесь:

public class MemberInfo {

    public string Username { get; set; }
    public string FirstName { get; set; }
    public string MiddleName { get; set; }
    public string LastName { get; set; }
    public string Fullname { get; set; }
    public string AddressPrimary { get; set; }
    public string AddressSecondary { get; set; }
    public string Zip { get; set; }
    public string Country { get; set; }
    public string HomepageUrl { get; set; }
    public string Id { get; set; }
    public string MemberNo { get; set; }
    public Boolean IsApproved { get; set; }
    public string Email { get; set; }
    public Boolean IsNotMember { get; set; }
    public Boolean IsUpdated { get; set; }
    public Boolean HasReceivedWelcomeMail { get; set; }
    public int RandomNumber { get; set; }
    public int MemberType { get; set; }

    public MemberInfo() { 

    }

    public MemberInfo(string _username, string _id) {
        Username = _username;

        MembershipUser userRequested = Membership.GetUser(Username);

        ProfileBase profile = ProfileBase.Create(Username);

        IsApproved = userRequested.IsApproved;

        FirstName = profile.GetPropertyValue("Firstname").ToString();
        MiddleName = profile.GetPropertyValue("Middlename").ToString();
        LastName = profile.GetPropertyValue("Lastname").ToString();
        AddressPrimary = profile.GetPropertyValue("AddressPrimary").ToString();
        AddressSecondary = profile.GetPropertyValue("AddressSecondary").ToString();
        Zip = profile.GetPropertyValue("Zip").ToString();
        Country = profile.GetPropertyValue("Country").ToString();
        HomepageUrl = profile.GetPropertyValue("HomepageUrl").ToString();
        HasReceivedWelcomeMail = Boolean.Parse(profile.GetPropertyValue("WelcomeMailSent").ToString());

        if (FirstName.Length > 2) {
            string strFullName = FirstName + " " + MiddleName + " " + LastName;
            Fullname = strFullName.Replace("  ", " ");
        }
        else {
            Fullname = Username;
        }

        MemberNo = profile.GetPropertyValue("MemberNo").ToString();
        IsNotMember = Boolean.Parse(profile.GetPropertyValue("NotMember").ToString());
        Email = userRequested.Email;
        Id = _id;

        if (profile.GetPropertyValue("Description").ToString() != "") {
            IsUpdated = true;
        }
        else {

            if (umbraco.library.GetXmlNodeById("1352").Current.SelectSingleNode("node [@nodeName='" + Username + "']/node") == null) {
                IsUpdated = false;
            }
            else {
                IsUpdated = true;
            }

        }
        RandomNumber = ss.NumberStuff.GenerateRandomNumber(0, 10000000);

        MemberType = 1;

        if (IsApproved == false && HasReceivedWelcomeMail == false) { // Not yet approved
            MemberType = 1;
        }

        if (IsApproved == false && HasReceivedWelcomeMail == true) { // Deleted
            MemberType = 2;
        }

        if (IsApproved == true && IsNotMember == false) { // Members
            MemberType = 3;
        }

        if (IsApproved == true && IsNotMember == true) { // Administrators
            MemberType = 4;
        }

    }

    private static object objLock = new object();

    public List<MemberInfo> GetAllMembers() {
        return GetAllMembers(false);
    }

    public List<MemberInfo> GetAllMembers(Boolean bIncludeAdministrators) {

        MembershipUserCollection allUsers;
        lock (objLock) {
            allUsers = Membership.GetAllUsers();
        }

        List<MemberInfo> memberInfoList = new List<MemberInfo>();

        foreach (MembershipUser userCurrent in allUsers) {
            MemberInfo mInfo = new MemberInfo(userCurrent.UserName, userCurrent.ProviderUserKey.ToString());
            if (mInfo.Id == "0") {
                continue;
            }

            if (mInfo.IsNotMember == true && bIncludeAdministrators == false) {
                continue;
            }

            memberInfoList.Add(mInfo);
        }

        return memberInfoList;

    }

    public static String GetMemberTypeName(int intMemberType) {

        switch (intMemberType) {

            case 1: {
                return "Endnu ikke godkendt";
            }

            case 2: {
                return "Slettet";
            }

            case 3: {
                return "Medlem";
            }

            case 4: {
                return "Administrator";
            }

            default: {
                return "";
            }
        }

    }

}

Заранее спасибо:)

Редактировать: Добавлен новый источник MemberInfo.cs и обновлено, какое сообщение об ошибке я получаю. Обратите внимание, что трассировка стека все еще старая, поэтому номера строк, на которые она ссылается, могут быть немного неправильными.

Редактировать: много информации об ошибке было изменено. Добавлен новый MemberInfo.cs Удален код из метода входа в систему, поскольку теперь я знаю, что это не является причиной ошибки.

Ответы [ 6 ]

3 голосов
/ 26 октября 2010
[ArgumentException: Item has already been added. Key in dictionary: 'administratoren' Key being added: 'administratoren']

Кажется, у вас есть повторяющиеся имена пользователей в allUsers (var allUsers = ...), но вы только что определили переменную, так что нет никакой возможности поместить в нее еще один 'администратор' и получить исключение притой же линии, если что-то не происходит на той же линии.Поскольку членство не допускает дублирования KEY (имен пользователей), проблема заключается в приведении, которое происходит после получения пользователей в конце одной строки кода:

Line 71: var allUsers = from u in Membership.GetAllUsers().Cast() select u;

изменить на:

Line 71: var allUsers = from u in Membership.GetAllUsers().Cast<MembershipUser>() select u;

Также использование var или написание множества операторов в одной строке кода не очень хорошая идея.

1 голос
/ 08 ноября 2010

Оказывается, что сайт хранит некоторые данные сеанса в таблице.
В некоторых случаях эта таблица устаревает, а затем сайт падает.
Я добавил некоторый код очистки для очистки таблицывот-вот произойдет ошибка.

Спасибо всем, кто пытался мне помочь:)

0 голосов
/ 03 ноября 2010

@ EDIT:

Удалите static из следующей строки или вызовите функцию без bIncludeAdministrators:

Line 108: public static List GetAllMembers(Boolean bIncludeAdministrators) 

Причина: Каждый запрос вASP.NET обслуживается другим потоком из пула потоков ASP.NET, если два потока достигают этой линии одновременно, то GetAllMembers() вызывается из двух разных потоков одновременно.Кажется, что этот метод не реализован в поточно-ориентированном режиме и не обеспечивает блокировку над HashTable при добавлении к нему элементов.Затем последний поток попытается добавить тот же ключ к HashTable.

0 голосов
/ 26 октября 2010

Может быть, вы должны переопределить равенство и операцию хеширования для вашей сущности. Например, по идентификатору.

0 голосов
/ 19 октября 2010

Это не вызвано кодом входа в систему. Похоже, что это ошибка в файле MemberInfo.cs. Этот код вызывается из пользовательского элемента управления GetMemberTopList. Если вы опубликуете этот код, мы сможем помочь вам, но я предлагаю подключить отладчик и посмотреть на стек при возникновении исключения.

0 голосов
/ 15 октября 2010

Я прочитал вашу проблему. У меня нет большого опыта работы в веб-приложении. Одна вещь состоит в том, что «Hash Table» может содержать только уникальные значения. когда вы пытаетесь ввести тот же ключ и если он уже есть в хэш-таблице, он выдаст вам ошибку.

Итак, я бы предложил вам использовать метод аутентификации. когда мы используем предоставляемые Microsoft функции, мы не можем контролировать их. так что лучше используйте свою собственную аутентификацию и управляйте ими.

...