18

2009年6月8日15:52更新短い回答NO元の質問:

廃棄に関するSPWeb.Siteのガイダンスを提供するリファレンスが見つかりません。SharePointオブジェクトの破棄に関するより一般的なベストプラクティスのドキュメントをいくつか確認しました。

残念ながら、これらのガイドラインのいずれもSPWeb.Siteについて言及していません。コンテキストを与えるために、メソッドの引数としてSPWebを受け入れるパブリック拡張APIを作成しています。

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

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

     **OR** ??

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

SPWebのrefelectorでClose()メソッドを調べましたが、これはSPWeb.Dispose()によって呼び出され、実際のSPSiteメンバーフィールドが破棄されることを示すものは何もありません。

更新:2009年6月8日13:47

アレックスの提案で

「100回実行されるループに入れ、WSSv3およびMOSS2007でのSPSite/ SPWebリークのトラブルシューティングで説明されているSPRequestStackTraceレジストリキーを使用して、テストコードが問題の原因であることを確認します。」

Webパーツ内に含まれている次のコードを実行しました。

 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を破棄する必要はないことを示唆しています。このテーマについてもっと情報を持っている人から具体的な答えを得るのは本当に素晴らしいことです。

更新:2009年6月8日14:52 グレッグのコメントによるプロンプトm_Siteの割り当てを作成しましたが、最終的には常に内部コンストラクターを介してSPWebに渡されるようです。たとえば、SPWeb.OpenWebはこれを新しいSPWeb()に渡します。したがって、SPWeb.Siteは破棄されるべきではないと確信しています。破棄された場合、実際に問題が発生する可能性があります。

4

8 に答える 8

8

カークの答えは正しいです。SPWebを作成する前に、SPSiteへのハンドルが必要です。これは、SPWeb.Siteを呼び出すときに使用するのと同じSPSiteインスタンスです。

その意味を考えてみましょう。SPSiteの作成を制御していないが、その子Webの1つが外部コードから渡され、制御が呼び出し元のコードに戻ったときにサイトを破棄した場合は、次のようになります。彼らがしていないかもしれないサイトを処分しました!呼び出し元のコードに身を任せてください。SPWebをメソッドに渡し、そのメソッドが完了すると、使用していたSPSiteが閉じられます。割り当てたリソースをクリーンアップするのは、常にインスタンス化者の責任です。この場合、SPSiteを廃棄しないでください。

于 2009-08-06T14:21:37.423 に答える
5

頭のてっぺんから考えているだけ(時々危険)...

SPSiteがなければSPWebを実際に持つことはできないようです。したがって、SPSiteを経由せずにSPWebを取得した場合(新しいSPSiteを実行するか、提供されたSPSiteを実行することによって)、おそらくSPSiteの破棄について心配する必要はありません。

ただし、これは単なる推測です。良い質問!

于 2009-08-06T12:19:09.143 に答える
2

これは明確ではありません。Stefanのブログには、「コードが所有するSPSiteオブジェクトとSPWebオブジェクトのみを破棄するようにする必要があります」と記載されています。次に、このパターンがリークすることを示すMichael Washam(Microsoft)からのこのスレッドがあります。

別のリファレンスを見つけることができないか、他の誰かが知っている場合を除いて、開発サーバーでテストして、この質問への回答として結果を追加してみませんか?100回実行されるループに入れ、WSSv3およびMOSS2007でのSPSite/ SPWebリークのトラブルシューティングで説明されているSPRequestStackTraceレジストリキーを使用して、テストコードが問題の原因であることを確認します。

于 2009-08-06T10:09:06.470 に答える
2

Reflectorは、これがSiteプロパティを呼び出すときにSPWebオブジェクト内で実行されるコードであることを示しています。

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

新しいSPSiteオブジェクトを作成するのではなく、すでに持っているオブジェクトを返すだけです。必要に応じて、SPWeb.Dispose()が処理します。だから、あなたはそれを安全に使うことができます、そして私はそれを処分することを避けます、SPWebの依存関係があなたにすべて不安定にならないように。

于 2009-08-06T13:12:09.227 に答える
1

SPDisposeCheckを使用してアセンブリをチェックしようとしましたか?おそらくそれはあなたにあなたの問題を処理する方法のヒントを与えるでしょう。

于 2009-08-06T10:04:06.463 に答える
1

deposeを呼び出しても、呼び出したものがクラッシュしない場合は、経験則として、SharePointコードでこのパターンをよく使用します。私が従うもう1つのルールは、オブジェクトに純利益をもたらさない拡張機能を作成しないようにすること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.SiteSPContextサイトが正しくクリーンアップされていることがわかっているため、自己が正しくクリーンアップされた後にクリーンアップすることです(これは、数少ないオブジェクトの1つです)。あなたに質問します。(OpenWeb経由で取得したWebをリークする必要があることに注意してください)

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

あなたSPSiteはウェブパーツで何かをするようにする必要があります。

  1. web.Siteプロパティは、実際には、Webが破棄された場合、それ自体の後にクリーンアップされます。
  2. SPSiteオブジェクトを渡して、関数のユーザーに心配させてみませんか?ほとんどの場合、とにかくSPContext.Current.Siteを使用して呼び出していると思います。
  3. ほとんどの場合、アクセス許可について心配する必要があります。すべてのdllがGACに含まれるわけではないため、新しい拡張メソッドを作成するときに、ラッパーを作成する必要があります。SPSecurity.CodeToRunElevated

それらを念頭に置いて、私はこれをとして書くことになります。。。SPSiteは、どのスコープに配置されているかを追跡できないため、引数としてSPSiteが渡されるため、この場合、Disposeチェックはオフになります。

public static void GetWebPartFromCatalog(this SPSite site, string webPartName) {
     SPSecurity.CodeToRunElevated( () => {
         using(SPSite suSite = new SPSite(site.Id)){
             //do what you need to do
         }
     };
}
于 2009-08-06T14:12:48.277 に答える
1

Stefan Gobnerには、これに関する優れた記事があります 。WSSv3およびMOSS2007でのSPSite/SPWebリークのトラブルシューティング

...そして、コードベースでSPDisposeチェックツールを使用してください。

于 2009-08-06T14:25:55.840 に答える
0

新しいオブジェクトの場合は、SPSite/SPWebインスタンスを削除する必要があります

例えば

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

ここで使用すると、オブジェクトの削除が処理されますが、SPContext.Currentからオブジェクトの参照を取得した場合は、参照がSPContext.Currentから利用可能である必要があるため、オブジェクトを明示的に破棄しないでください。

于 2011-04-19T15:16:53.350 に答える