SPWeb.Site, вы должны вызвать Dispose () на нем? - PullRequest
18 голосов
/ 06 августа 2009

Обновлено 06.08.2009 15: 52 : Краткий ответ НЕТ . Оригинальный вопрос:

Я не могу найти ссылку, которая бы давала руководство по SPWeb.Site относительно утилизации. Я ознакомился с некоторыми из наиболее популярных руководств по утилизации объектов SharePoint:

К сожалению, ни одно из этих руководств не упоминает SPWeb.Site. Чтобы дать некоторый контекст, я пишу общедоступный API-интерфейс расширения, который принимает SPWeb в качестве аргумента для метода, т.е.

public static void GetWebPartFromCatalog(this SPWeb web, string webPartName)
{
     ......

     SPSite site = web.Site;
     ......

     **OR** ??

     using (SPSite site = web.Site)
     {
         ....
     }
}

Я выглядел как метод Close () в рефлекторе для SPWeb, который вызывается SPWeb.Dispose (), и в нем нет ничего, что указывало бы на фактическое удаление поля члена SPSite.

Обновление: 08.06.2009 13: 47

В Алекс предложение

«Поместите его в цикл, который выполняется 100 раз, и используйте раздел реестра SPRequestStackTrace, описанный в разделе« Устранение утечек SPSite / SPWeb »в WSS v3 и MOSS 2007, чтобы убедиться, что ваш тестовый код является источником проблемы».

Я запустил следующий фрагмент кода, включенный в веб-часть:

 for (int i = 0; i < 100; i++)
 {
     using (SPWeb web = SPContext.Current.Site.OpenWeb(""))
     {
            SPSite site = web.Site;
            Debug.WriteLine(site.Url);
     }
 }

Ничего не появилось в журналах SharePoint.

Хотя я бы не решился сделать какие-либо реальные выводы из этого наивного эксперимента, он предположил бы, что не необходимо для утилизации SPWeb.Site. Было бы очень приятно получить конкретный ответ от кого-то более осведомленного по этому вопросу.

Обновление: 08.06.2009 14: 52 В ответ на комментарий Грега я разработал назначения m_Site, и кажется, что он всегда передается в SPWeb через внутренние конструкторы. Например. SPWeb.OpenWeb передает this новому SPWeb (). Поэтому я более уверен, что SPWeb.Site должен быть утилизирован , а не , что может привести к проблемам, если это так.

Ответы [ 8 ]

8 голосов
/ 06 августа 2009

Ответ Кирка правильный. У вас должен быть некоторый дескриптор SPSite до того, как SPWeb может быть создан, и это тот же экземпляр SPSite, который будет у вас при вызове SPWeb.Site.

Давайте подумаем над последствиями этого - если вы не контролируете создание SPSite, но одна из его дочерних сетей передается вам из внешнего кода, и вы удаляете сайт, когда управление возвращается вызывающему коду. , вы распорядились сайтом, с которым им не обойтись! Поставьте себя на место вызывающего кода: вы передаете SPWeb в метод, и когда этот метод завершается, используемый вами SPSite закрывается. Ответственность за очистку ресурсов, которые они выделяют, всегда лежит на инстанциаторе. Не выбрасывайте SPSite в этом случае.

5 голосов
/ 06 августа 2009

Просто размышляю над головой (иногда опасно) ...

Кажется, что у вас не может быть SPWeb без SPSite. Итак, если вы получили SPWeb без прохождения SPSite для его получения (либо путем создания нового SPSite, либо предоставления вам), то вам, вероятно, не нужно беспокоиться об утилизации SPSite.

Это всего лишь гипотеза. Хороший вопрос!

2 голосов
/ 06 августа 2009

Reflector сообщает нам, что это код, который запускается внутри объекта SPWeb при вызове свойства Site:

public SPSite Site
{
    get
    {
        return this.m_Site;
    }
}

Это не создание нового объекта SPSite, а просто возвращение того, который у него уже был, что будет зависеть от SPWeb.Dispose (), чтобы позаботиться при необходимости. Таким образом, вы можете безопасно использовать его, и я бы не стал его утилизировать, чтобы не зависеть от SPWeb-зависимостей.

2 голосов
/ 06 августа 2009

Это не ясно. Есть блог Стефана , в котором говорится «Вы должны обеспечить удаление только тех объектов SPSite и SPWeb, которые принадлежат вашему коду» * . Затем есть этот поток от Michael Washam (Microsoft), который заявляет, что этот шаблон действительно течет.

Если вы не можете найти другую ссылку или кто-то другой знает, почему бы вам не проверить ее на своем сервере разработки и не добавить свои результаты в качестве ответа на этот вопрос? Поместите его в цикл, который выполняется 100 раз, и используйте раздел реестра SPRequestStackTrace, описанный в Устранение утечек SPSite / SPWeb в WSS v3 и MOSS 2007 , чтобы проверить, что ваш тестовый код является источником проблемы.

1 голос
/ 06 августа 2009

У Штефана Гобнера есть отличная статья на эту тему: Устранение неполадок утечек SPSite / SPWeb в WSS v3 и MOSS 2007

... И обязательно используйте SPDispose check tool на вашей кодовой базе.

1 голос
/ 06 августа 2009

Я часто использую этот шаблон в своем коде SharePoint, как правило, если вызов depose не приводит к сбою всего, что я называю. Другое правило, которому я следую, это то, что я стараюсь не создавать расширения, которые не вызывают чистый выигрыш в SPRequest объектах (объект SPRequest - это объект .net, который общается со всеми тяжеловесными ком-объектами)

теперь разбиваем ваш пример

 for (int i = 0; i < 100; i++)
 {
     using (SPWeb web = SPContext.Current.Site.OpenWeb(""))
     {
            SPSite site = web.Site;
            Debug.WriteLine(site.Url);
     }
 }

Ключевым моментом здесь является SPContext.Current.Site. SPContext будет очищаться после того, как он сам правильно (один из немногих объектов, который делает), так как мы знаем, что сайт очищен правильно, я ожидаю, что сети были очищены Однако это далеко не правильный ответ на ваш вопрос. (обратите внимание, что вы должны вытекать из Интернета через OpenWeb)

public static void GetWebPartFromCatalog(this SPWeb web, string webPartName)

вам нужно получить SPSite для работы с веб-частями.

  1. свойство web.Site на самом деле очищается после того, как само себя утвердит, если сеть удалена.
  2. Почему бы просто не передать объект SPSite и позволить пользователю функции беспокоиться об этом? В большинстве случаев я думаю, что они все равно будут звонить, используя SPContext.Current.Site.
  3. Большую часть времени мне приходится беспокоиться о разрешениях, не все наши библиотеки попадают в GAC, поэтому, когда я пишу новый метод расширения, мне приходится оборачивать его SPSecurity.CodeToRunElevated

Имея это в виду, я бы написал это как. , , Теперь проверка Dispose сработает в этом случае, потому что SPSite передается в качестве аргумента, потому что он не может отследить, в какой области он расположен.

public static void GetWebPartFromCatalog(this SPSite site, string webPartName) {
     SPSecurity.CodeToRunElevated( () => {
         using(SPSite suSite = new SPSite(site.Id)){
             //do what you need to do
         }
     };
}
1 голос
/ 06 августа 2009

Вы пытались проверить свою сборку с помощью SPDisposeCheck ? Возможно, это даст вам совет, как справиться с вашей проблемой.

0 голосов
/ 19 апреля 2011

Вам необходимо удалить экземпляр SPSite / SPWeb, если это новый объект

например

using(SPSite site = new SPSite("url"))
{
    DoSomething;
}

здесь с помощью позаботится об удалении объекта однако, если вы получили ссылку на объект из SPContext.Current, вам не следует явно удалять объект, так как ссылка должна быть доступна из SPContext.Current.

...