2009-03-18 5 views
3

Как удалить ссылку на подвэб в следующем запросе?Использование linq с Sharepoint и утилизацией объектов

using (SPSite spSite = Utility.GetElevatedSite(_rootUrl)) 
{ 
    from SPWeb web in spSite.AllWebs 
    where web.ServerRelativeUrl.ToLower() == path 
    from SPWeb subWeb in web.Webs        
    select subWeb 
} 

ли я даже не нужно беспокоиться о распоряжении веб-каталога, если IAM уже wraped в SPSite в заявлении Использование?

Edit:

Это хорошая идея тоже называют сбор мусора в этом случае?

ответ

6

К сожалению, вы делаете. Проблема начинается с свойства SPSite.AllWebs. Свойство SPWeb.Web также небезопасно.

Просьба this very thorough reference о ситуациях, когда вам нужно беспокоиться об удалении объектов SharePoint.

(Я предлагаю добавить это в свой чит-лист SharePoint).

В результате я чувствую, что существующую объектную модель SharePoint нельзя безопасно использовать с синтаксисом LINQ.

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

Edit: SPDisposeCheck инструмент представляет собой консоль приложения командной строки, которая будет сканировать сборки .NET и предупредить вас о неотчужденном ссылке на основе принципов выше наилучшей практики. Проверьте это.

http://code.msdn.microsoft.com/SPDisposeCheck

http://blogs.msdn.com/sharepoint/archive/2008/11/12/announcing-spdisposecheck-tool-for-sharepoint-developers.aspx

+0

Sahrepoint в сторону, я полагаю, что его невозможно рассеять внешние ресурсы при использовании linq вообще, правильно? – 2009-03-18 06:20:25

+0

Дело с SharePoint заключается в том, что управляемая часть очень маленькая. Но экземпляры SPWeb и SPSite содержат ссылку на неуправляемый объект SPRequest, который может составлять 1-2 МБ. Когда GC не происходит достаточно быстро, у SharePoint заканчивается память. –

+0

Я понимаю, что, когда мы используем LINQ с DataContext, вы удаляете весь файл данных после завершения LINQ с ним, который освобождает внешние ресурсы. Так что да, это будет мое предположение, что LINQ не собирается распоряжаться разработчиком. –

2

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

Реализация этого безопасного решения для LINQ на самом деле довольно проста в C#. Вы можете найти полную информацию в this post, но короткая версия - это то, что итератор C# может обрабатывать вас. С помощью моего метода AsSafeEnumerable() расширения, ваш код относительно безопасным написано так:

using (SPSite spSite = Utility.GetElevatedSite(_rootUrl)) 
{ 
    var sw = from SPWeb web in spSite.AllWebs.AsSafeEnumerable() 
      where web.ServerRelativeUrl.ToLower() == path 
      from SPWeb subWeb in web.Webs.AsSafeEnumerable()  
      select subWeb; 
    foreach(SPWeb aSubWeb in sw) 
    { 
     // Do something 
    } 
} 

Теперь результат вашего запроса, который я присвоенного sw, ленивый итератор типа IEnumerable<SPWeb>. Когда вы перечислите этот результат, каждый SPWeb будет удален, когда перечислитель перейдет к следующему элементу. Это означает, что небезопасно использовать ссылку SPWeb или любой созданный из нее объект SP * (SPList и т. Д.), За пределами вашего цикла foreach. Также sw небезопасно использовать за пределами этого блока using, потому что номер итератора будет привязан к теперь расположенному SPSite.

Тем не менее, код, подобный этому, перечисляет все веб-страницы (дважды!), Является чрезвычайно дорогостоящим.Существует почти наверняка более эффективный способ, которым это может быть реализовано, если только с помощью spSite.AllWebs[path] вместо from/where.

Что касается сборки мусора, эти объекты требуют удаления из-за неуправляемой памяти, выделенной для того, что GC даже не знает.

И, наконец, предостережение о вашей утилите GetElevatedSite. Если вы используете RunWithElevatedPrivileges в своем вспомогательном методе, чтобы получить свой повышенный SPSite, есть ряд проблем, с которыми вы могли столкнуться, вернув SPSite из этого повышенного контекста. Если возможно, я бы предложил использовать олицетворение SPSite - мой предпочтительный метод описан here.

+0

Приветствие приятеля, очень полезно. Обычно я [выбираю что-то] всякий раз, когда я использую запрос linq. Я не могу себе представить, как программировать объектную модель без linq. ЕСЛИ филиалы будут на уровне сервера глубже! Но я полагаю, что есть pro/con с обоими методами ... – 2009-04-02 09:27:27

+0

Конечно, я действительно начинаю вникать в это. Пока вы выбираете материал, отличный от SharePoint, вы в порядке, вы просто не можете возвращать объекты, зависящие от теперь расположенного Интернета. И вы всегда можете добавить больше LINQ ниже для запроса в списки и элементы. Наслаждайтесь! – dahlbyk

Смежные вопросы