Подтвердить что ты не робот

SPWeb.Site, следует ли вам называть Dispose()?

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

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

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

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

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

     **OR** ??

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

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

Обновление: 06/08/2009 13:47

В предложение Alex

"Поместите его в цикл, который выполняется 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. Было бы очень полезно получить конкретный ответ от кого-то, кто более информирован по этому вопросу.

Обновление: 06/08/2009 14:52 Подготовлено Greg Comment Я разработал назначения m_Site и, похоже, он в конечном счете всегда передается в SPWeb через внутренние конструкторы. Например. SPWeb.OpenWeb переходит в этот к новому SPWeb(). Поэтому я уверен, что SPWeb.Site должен быть не удален, действительно может вызвать проблемы, если это было.

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

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

Ответ 3

Это не ясно. Существует блог Stefan, в котором указано . Вам нужно убедиться, что вы только размещаете объекты SPSite и SPWeb, которыми принадлежит ваш код.. Тогда есть этот поток от Michael Washam (Microsoft), в котором говорится, что этот шаблон просачивается.

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

Ответ 4

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

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

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

Ответ 5

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

Ответ 6

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

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

 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, чтобы сделать что-то с веб-частями.

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

С этими соображениями я в конечном итоге напишу это как., теперь Dispose check будет отключен в этом случае, потому что 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
         }
     };
}

Ответ 8

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

например,

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

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