В чем опасность использования статического класса, содержащего объект SPWeb?

sharepoint.stackexchange https://sharepoint.stackexchange.com//questions/35551

  •  09-12-2019
  •  | 
  •  

Вопрос

При создании решений SharePoint 2010 я часто создаю статический класс, содержащий вспомогательные методы и списки, документы, элементы списков и т. д., которые я часто использую.В чем опасность помещения туда моего объекта SPWeb?Или SPSite, если на то пошло?

Мой статический класс будет содержать такой метод:

    public static SPWeb webObject;

    public static SPWeb WebObject()
    {
        if (webObject != null)
            return webObject;
        else if (SPContext.Current != null)
        {
            webObject = SPContext.Current.Web;
        }

        return webObject;
    }

Таким образом, я могу заполнить веб-объект в любое время или просто вызвать метод, который вернет веб-объект или SPContext.Current.Web, если веб-объект имеет значение null.

Поэтому вместо того, чтобы писать мой код, например:

SPWeb web = site.RootWeb;
SPList list = web.Lists[listGuid];

Это будет выглядеть так:

SPList list = SharePointState.WebOject().Lists[listGuid];

Таким образом, я сэкономлю лишнюю строку кода, и мне не придется постоянно инициализировать объект SPWeb.

Теперь удаление объекта SPWeb сделало бы эту идею бессмысленной, поскольку статический метод просто воссоздавал бы объект SPWeb каждый раз, когда я его вызываю.Будет ли эта безумная идея истощать ресурсы и замедлять работу моего решения?Каковы некоторые опасности этого?

Это было полезно?

Решение

Это плохо по 3 причинам:

  1. Это приведет к ошибке. static означает, что он используется всеми потоками на протяжении всего срока службы AppDomain.Когда пользователь A переходит в /web1, а пользователь B через секунду переходит в /web2, этот код попытается выполниться так, как если бы он находился в /web1.

  2. Это может вызвать утечку памяти. Удерживать паутину дольше, чем это абсолютно необходимо, почти всегда очень плохая идея.В этом случае вы держите только одну сеть (хотя см. выше, почему это плохо), но это отражает неправильное понимание того, как на самом деле работает SPWeb.Вам следует открывать их как можно позже и избавляться от них как можно раньше;и если ты не тот, кто звонит Open(), тогда оставь их, черт возьми, в покое!

  3. Это приведет к проблемам с производительностью и непредвиденным ошибкам. Хранение объектов SPWeb в нескольких потоках не поддерживается.В журналах ULS вы начнете видеть ошибки, говорящие что-то вроде «Невозможно закрыть SPRequest;вы можете открывать и закрывать веб-сайты в разных потоках». Я видел, как это вызывало всевозможные странные проблемы, например, вызывало резкий скачок нагрузки SQL Server и сайты переставали отвечать на запросы на несколько минут.

Уроки выучены:

  • SPContext.Current уже знает, как отслеживать и управлять тем, какой SPWeb является «подходящим» для текущего контекста вызова.Доверьтесь этому.
  • Если вы не открыли веб-сайт, не закрывайте его.(В более общем плане, если вы не создавали IDisposable предмет - он был вам передан - не выбрасывайте его.
  • Всегда ждите до последнего момента, прежде чем открывать SPWeb, и быстро сделайте с ним то, что вам нужно, а затем закройте его.

Другие советы

Кто-то уже сделал то, что вы хотите, гораздо лучше. На самом деле, вы используете его в своем примере кода:

public static SPWeb WebObject()
{
    if (webObject != null)
        return webObject;
    else if (SPContext.Current != null)
    {
        webObject = SPContext.Current.Web;
    }

    return webObject;
}
.

Вы используете spcontext.courent.web как A Static Header здесь!

Ваши следующие два примера кода совсем не эквивалентны

SPWeb web = site.RootWeb;
SPList list = web.Lists[listGuid];
.

Это действует на roote web, если коллекция сайта

SPList list = SharePointState.WebOject().Lists[listGuid];
.

Это действует на текущем веб-сайте, независимо от его глубины в иерархии сайта.

Вы уже можете использовать следующую конструкцию:

SPList list = SPContext.Current.Web.Lists[listGuid];
.

Вы не только пытаетесь изобретать колесо, вы начинаете его как квадрат. SharePoint уже имеет свой собственный процесс мусора, который отслеживает объекты SPWEB и SPSITE и утилизируют их, если он думает, что они были слишком долго. Однако можно, однако можно управлять объемом способом, похожим на то, что вы делаете, но вы должны поссорить еще один уровень абстракции и внедрять репозитории, которые правильно обрабатывают объекты SP *. Эти репозитории вы можете создавать статические, синглтоны, что все, что подходит для ваших узоров.

Знайте также, что объекты, такие как SPContext.Current.Web и Spsite.rootweb уже частично кэшированы. Используя то же самое часто над обычным сеансом просмотра, не означает полного разрыва и настройки каждый раз.

Плохая идея, статический класс в веб-приложении (вроде SharePoint) означает, что тот, кто посещает этот сайт, сначала запускает создание статического объекта.Любой пользователь после этого повторно использует тот же объект, что означает, что любой последующий пользователь попытается использовать контекст первого пользователя.Что такое не только плохая идея (например, безопасность Raagrding), но, вероятно, не собирается работать, видя как HTTP, в основном без гражданства, поэтому любой SPContext будет утилизирован после каждого запроса, что приведет к утечке памяти для следующего запроса («Spexception: Попытка использовать объект SPWEB, который был закрыт или расположены, и больше не действителен »).

Никогда не закрывайте, утилизируйте или повторно используйте объект SPContext (в значительной степени правило, если вы не «владели» объектом, то есть вы не создали его самостоятельно, используя, например, конструктор, не утилизируйте /Закройте его. Я предлагаю регулярно использовать SpdisPosecheck, чтобы проверить свой код на возможные утечки памяти!

Я согласен с последним пунктом плаката, что если вы не «владеете» объектом, который вы не должны распоряжаться этим. Однако я полностью не согласен с идеей избежать статического класса.

Термин «статический» действительно просто означает общий. Общие экземпляры объектов используются повсюду в ASP.NET. API кэша и состояние приложения являются идеальными примерами. Нет абсолютно ничего плохого в использовании статических или общих экземпляров, где это применимо.

Один отличный пример - идея httpcontext. Этот контекст будет точно таким же для каждого пользователя, который посещает сайт. Вы никогда не захотите, чтобы это было ничего, кроме всего поделиться; Это обязательно должно быть одинаковым для каждого пользователя.

В моей книге статические объекты просто отлично в веб-приложении. Я скажу, что вы должны избегать использования модели Singleton; Это приходит со всеми видами головных болей. Но простой статический объект в порядке. Христос ... Любые методы расширения, которые вы создаете, являются частью статического класса!

до тех пор, пока они используются с целью, а не только ради использования чего-то, что «общий» статический класс полностью приемлемо.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с sharepoint.stackexchange
scroll top