2009-08-06 7 views
18

Zaktualizowano 06/08/2009 15:52: Krótka odpowiedź NO. Oryginalne pytanie:SPWeb.Site, czy należy wywołać na nim funkcję Dispose()?

Nie mogę znaleźć żadnego odniesienia, które zawiera wskazówki dotyczące SPWeb.Site w zakresie usuwania. Poszedłem za jedne z bardziej popularnych dokumentacji najlepszych praktyk w zakresie usuwania obiektów SharePoint:

Niestety żaden z tych wytycznych wspomnieć SPWeb.Site. Aby dać pewien kontekst, Piszę API przedłużacza publiczna, która akceptuje SPWeb jako argument do metody a mianowicie:

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

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

    **OR** ?? 

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

szukałem jako metodę Close() w refelector dla SPWeb, który jest nazywany przez SPWeb.Dispose() i nie ma w nim nic, co wskazywałoby na faktyczne usunięcie pola członka SPSite.

Aktualizacja: 06/08/2009 13:47

Na Alex's sugestia

„Umieścić go w pętli, czyli 100 razy i użyj klucza rejestru SPRequestStackTrace opisaną w rozwiązywaniu SPSite/SPWeb przecieki w WSS v3 i MOSS 2007, aby sprawdzić, czy Twój kod testowy jest źródłem problemu. "

Pobiegłem następujący kawałek kodu dołączonego wewnątrz webpart:

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

Nic w logach SharePoint pojawił.

Chociaż zawaham się wyciągnąć jakiekolwiek prawdziwe wnioski z tego naiwnego eksperymentu, sugerowałoby to, że jest to , a nie niezbędne do pozbycia się SPWeb.Site. Byłoby naprawdę miło uzyskać konkretną odpowiedź od kogoś bardziej poinformowanego na ten temat.

Aktualizacja: 08.06.2009 14:52 Wspomagana przez Grega komentarz wypracowałem cesji m_Site i wydaje się to ostatecznie zawsze przeszły do ​​SPWeb poprzez wewnętrzne konstruktorów. Na przykład. SPWeb.OpenWeb przechodzi w ten do nowego SPWeb(). Tak więc jestem bardziej pewny, że SPWeb.Site powinien być usunięty, a może być przyczyną problemów, gdyby tak było.

+0

Patrząc na to, nie jest jasne. Zadałem to samo pytanie, co komentarz do postu Rogera Lamb, ale nie otrzymałem odpowiedzi. –

+0

Moim zdaniem, i to jest po prostu opinia, nie, nigdy nie powinieneś mieć do czynienia z tym obiektem. Czemu? Cóż, jest zwracana przez właściwość z innego obiektu. Jeśli ten inny obiekt jest do dyspozycji, powinieneś wyrzucić * to * i pozwolić mu zadbać o własne zasoby. Nic, co czytasz z własności, nie powinno być usuwane przez twój własny kod, który byłby dla mnie błędem w tym systemie. –

+1

@ lasse-v-karlsen Zgadzam się z Tobą w 100%, jednak w interfejsie SharePoint API jest wiele dziwnych rzeczy i naprawdę musisz zrozumieć te lub ryzykować wyciek pamięci. Więc chociaż może to być błąd w API, chciałabym go zrozumieć, czy jest tam, czy nie :) –

Odpowiedz

8

Kirk's answer jest poprawna.Musisz mieć pewną obsługę SPSite przed utworzeniem SPWeb i jest to ta sama instancja SPSite, którą będziesz mieć podczas wywoływania SPWeb.Site.

Pomyślmy przez implikacji, które - jeśli nie kontrolują utworzenie SPSite, ale jeden z jego żeber dziecko jest przekazywane do was z kodu zewnętrznego i pozbyciem witrynę, gdy kontrola jest zwracana do powołania Kod, usuniesz stronę, której nie wolno Ci zrobić! Postaw się w kodzie wywołującym: przekazujesz SPWeb do metody, a kiedy ta metoda jest wykonywana, używany przez Ciebie SPS został zamknięty. Zawsze obowiązkiem podmiotu odpowiedzialnego za oczyszczanie środków, które przydzielają. Nie wyrzucaj SPSite w tym przypadku.

+0

Według tej samej teorii SPLimitedWebPartManager powinien również wyczyścić, ale nie robi! http://blogs.msdn.com/rogerla/archive/2008/02/12/sharepoint-2007-and-wss-3-0-dispose-patterns-by-example.aspx#SPDisposeCheckID_160 Czy istnieje ku temu powód lub kolejna niespójność w API? –

+0

@Alex Nie widzę, jak to jest to samo. W przykładzie, z którym się łączyłeś, SPSite i SPWeb oba muszą być jawnie wyczyszczone, * jak również * inna * sieć, która jest tworzona przez SPLimitedWebPartManager. –

+0

Bardzo dobrze włożyć Rex. Powinieneś zawsze myśleć o SPWeb jako "przynależącym" do SPSite, nigdy na odwrót. Zwłaszcza, że ​​przedwczesne wyrzucenie SPSite wywoła najpierw Dispose() na wszystkich utworzonych z niego SPWeb. W związku z tym zawsze zakładam, że program SPSite zostanie usunięty przez kod, który go utworzył. (* Artykuł wiki dokumentuje wszystkie znane przypadki, w których oczyszczanie SPSite jest Twoją pracą.) – dahlbyk

1

Czy próbowałeś sprawdzić swój zespół za pomocą SPDisposeCheck? Być może daje wskazówkę, jak sobie z tym poradzić.

+1

SPDisposeCheck sprawdza tylko te błędy na stronie "Najlepsze praktyki", jak sądzę. –

2

To nie jest jasne. Jest Stefan's blog które stwierdza „Trzeba upewnić się, że tylko wyrzucać SPSite i SPWeb obiekty kod posiada”. Następnie jest this thread z Michael Washam (Microsoft), który stwierdza przeciek tego wzoru.

Jeśli nie możesz znaleźć innego odniesienia lub ktoś wie, dlaczego nie przetestujesz go na serwerze programistycznym i nie dodasz wyników jako odpowiedzi na to pytanie? Umieść go w pętli, która działa 100 razy i użyj klucza rejestru SPRequestStackTrace opisanego w Troubleshooting SPSite/SPWeb leaks in WSS v3 and MOSS 2007, aby sprawdzić, czy źródłem kodu jest twój kod testowy.

+0

Dobra sugestia, dam zawód i opublikuję wyniki. –

+1

Wątek MSDN, do którego odnosi się odwołanie, używa antepattern do zwracania odniesienia SPWeb z metody pomocnika, popełniając dodatkowy (i bardziej szkodliwe) grzechu tworzenie się SPSite w procesie. Zamiast tego, ten kod powinien zostać refaktoryzowany na metody, które pochłaniają argument SPSite/SPWeb: http://solutionizing.net/2009/01/06/elegant-spsite-elevation/ – dahlbyk

5

Wystarczy myśleć poza czubek mojej głowy (czasami niebezpieczne) ...

Wydaje się, że tak naprawdę nie można mieć SPWeb bez posiadania SPSite. Tak więc, jeśli masz SPWeb bez przechodzenia przez SPSite, aby go zdobyć (albo robiąc nowy SPSite, albo dostarczony ci), to prawdopodobnie nie musisz się martwić o wyrzucenie SPSite.

To tylko przypuszczenie. Dobre pytanie!

+0

Jest to, ponieważ jest to metoda rozszerzenia dla SPWeb, program wywołujący mógł utworzyć obiekt SPSite. Jednak nie mam odniesienia do obiektu SPSite, stąd potrzeba używania SPWeb.Site. Które prowadzą do pytania, czy muszę po sobie posprzątać :) Mogę poprosić rozmówcę o dołączenie SPSite (dodać go do listy parametrów), ale nie chciałem zwiększać parametrów tej metody. –

+0

@Edward to jest najbardziej poprawna odpowiedź. Zobacz mój. –

2

Reflektor mówi nam, że jest to kod, który działa wewnątrz obiektu SPWeb kiedy zadzwonić właściwość strony:

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

To nie jest tworzenie nowego obiektu SPSite, tylko zwrócenie jeden to już, co bądź do SPWeb.Dispose(), aby zająć się, jeśli to konieczne. Możesz więc bezpiecznie z niego korzystać, a ja bym go unikał, aby nie uzależniały się od ciebie zależności SPWeb.

+2

Myślę, że to naprawdę zależy od sposobu przypisania m_Site. Korzystanie z analizy reflektorów, aby pokazać "przypisany przez" na m_Site pokazuje, że jest on przypisany w prywatnym składniku SPWebConstructor(), który jest przekazywany w witrynie za pośrednictwem listy konstruktorów wewnętrznych SPWeb .... W końcu SPWeb nigdy nie aktualizuje SPSite . –

1

Często używam tego wzorca w moim kodzie SharePoint jako reguły, jeśli wywołanie depose nie powoduje awarii czegokolwiek, co nazywam. Drugą regułą, którą przestrzegam jest to, że staram się nie tworzyć rozszerzeń, które nie powodują zysku netto w obiektach SPRequest (obiekt SPRequest jest obiektem .net, który komunikuje się z wszystkimi komendami wagi ciężkiej)

teraz zerwanie swój przykład

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

kluczem tutaj jest SPContext.Current.SiteSPContext będzie posprzątać po to self prawidłowo (jeden z niewielu obiektów, które nie), ponieważ wiemy, że strona jest czyszczona prawidłowo Spodziewam się, że wstęgi dostał oczyszczone, jednak jest to dalekie od prawidłowej odpowiedzi na twoje pytanie. (Uwaga powinna być wyciek wstęg dostałeś poprzez OpenWeb)

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

trzeba uzyskać SPSite zrobić coś z częściami internetowych.

  1. Właściwość web.Site w rzeczywistości czyści się po tym, jak JEŻELI sieć zostanie usunięta.
  2. Dlaczego po prostu nie przekazać obiektu SPSite i pozwolić użytkownikowi funkcji martwić się o to? W większości przypadków wydaje mi się, że będą wywoływać przy użyciu SPContext.Current.Site mimo to.
  3. Większość czasu muszę się martwić o uprawnieniach, nie każdy z naszych bibliotek DLL skończyć w GAC więc kiedy napisać nową metodę rozszerzenia I skończyć się koniecznością wrapper mu SPSecurity.CodeToRunElevated

z tymi w myślę, że w końcu to piszę. . . teraz utylizować check zgaśnie w tym przypadku, ponieważ The SPSite jest przekazywana jako argument, ponieważ nie można wyśledzić w jakim zakresie jest on umieszczony w.

public static void GetWebPartFromCatalog(this SPSite site, string webPartName) { 
    SPSecurity.CodeToRunElevated(() => { 
     using(SPSite suSite = new SPSite(site.Id)){ 
      //do what you need to do 
     } 
    }; 
} 
+0

Myślę, że masz na myśli SPSecurity.RunWithElevatedPrivileges - CodeToRunElevated jest typem delegata. Powiedział, że podniesienie domyślnie w metodzie pomocnika uderza mnie jako zły pomysł. A jeśli potrzebujesz podnieść, prawdopodobnie lepiej wykorzystać podszywanie się pod inne osoby: http://solutionizing.net/2009/01/06/elegant-spsite-elevation/ – dahlbyk

0

Trzeba usunąć instancję SPSite/SPWeb jeśli jest to nowy obiekt

np

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

tutaj wykorzystaniem zadba o usunięcie obiektu jednak jeśli masz odniesienie obiektu z SPContext.Current nie należy jawnie usuwać obiektu, ponieważ odniesienie powinno być dostępne z SPContext.Current.

Powiązane problemy