5

84 行目と 85 行目 (行を使用して積み重ねられた 2 つ) で次のメッセージが表示されます。

CA2000 : Microsoft.Reliability : メソッド 'RavenDataAccess.GetRavenDatabase()' で、オブジェクト '<> g_initLocal9' がすべての例外パスで破棄されません。オブジェクト '<>g _initLocal9' で System.IDisposable.Dispose を呼び出してから、オブジェクトへのすべての参照が範囲外になります。

DocumentStore は IDisposable を実装します。

なんで?DocumentStore オブジェクトを破棄するには、他にどのような方法がありますか? これらは using ブロックで作成され、catch ブロックで破棄します。これはどのように修正する必要がありますか?

private static IDocumentStore GetRavenDatabase()
{
    Shards shards = new Shards();

    try
    {
        using (DocumentStore docStore1 = new DocumentStore { Url = ConfigurationManager.AppSettings["RavenShard1"] })  // Line 84
        using (DocumentStore docStore2 = new DocumentStore { Url = ConfigurationManager.AppSettings["RavenShard2"] })  // Line 85
        {
            shards.Add(docStore1);
            shards.Add(docStore2);
        }

        using (ShardedDocumentStore documentStore = new ShardedDocumentStore(new ShardStrategy(), shards))
        {
            documentStore.Initialize();

            IndexCreation.CreateIndexes(typeof(RavenDataAccess).Assembly, documentStore);

            return documentStore;
        }
    }
    catch
    {
        shards.ForEach(docStore => docStore.Dispose());

        throw;
    }
}
4

4 に答える 4

2

新しく作成したすべての使い捨てオブジェクトを、考えられる例外パスに沿って確実に破棄する必要があります。下記参照:

private static IDocumentStore GetRavenDatabase()
{
    Shards shards = new Shards();
    DocumentStore docStore1 = null;
    DocumentStore docStore2 = null;

    ShardedDocumentStore shardedDocumentStore = null;
    ShardedDocumentStore tempShardedDocumentStore = null;

    try
    {
        docStore1 = new DocumentStore();
        docStore1.Url = ConfigurationManager.AppSettings["RavenShard1"];
        docStore2 = new DocumentStore();
        docStore2.Url = ConfigurationManager.AppSettings["RavenShard2"];

        shards.Add(docStore1);
        shards.Add(docStore2);

        tempShardedDocumentStore = new ShardedDocumentStore(new ShardStrategy(), shards);
        tempShardedDocumentStore.Initialize();

        IndexCreation.CreateIndexes(typeof(RavenDataAccess).Assembly, tempShardedDocumentStore);

        docStore1 = null;
        docStore2 = null;

        shardedDocumentStore = tempShardedDocumentStore;
        tempShardedDocumentStore = null;

        return shardedDocumentStore;
    }
    finally
    {
        if (tempShardedDocumentStore != null) { tempShardedDocumentStore.Dispose(); }
        if (docStore1 != null) { docStore1.Dispose(); }
        if (docStore2 != null) { docStore2.Dispose(); }
    }
}

CAは、インラインプロパティ初期化子に問題があるようですが、それらを分解すると、これは機能するはずです。重要なことは、tryブロックのどこで例外がスローされても、破棄できるすべての新しいオブジェクトがクリーンアップされるようにすることです。

戻る直前に不要になった一時参照(、、、)を設定することで、finallyブロックをチェックインして、実際に設定されているかどうかを確認できます。設定されていないnull場合docStore1は、どこかで例外が発生し、破棄できます。実行前にこのメソッドを終了します。docStore2tempShardedDocumentStorenull

とは、コレクションに追加されるときの一時的な参照であることに注意docStore1docStore2Shards

于 2012-04-12T15:33:02.663 に答える
1

using ステートメントのオブジェクト初期化子によって CA 警告が発生する理由は次のとおりです。

次のようなコード:

using (DocumentStore docStore2 = new DocumentStore { Url = ConfigurationManager.AppSettings["RavenShard2"] })  // Line 85
{
   ...
}

...オブジェクト初期化子の動作方法により、本質的に次のようになります。

DocumentStore foo = new DocumentStore;
foo.Url = ConfigurationManager.AppSettings["RavenShard2"];
using(DocumentStore docStore2 = foo)
{
   ...
}

ご覧のとおり、DocumentStore の初期化は using{} ブロックの外で行われるようになったため、temp.Url を設定する行で例外がスローされた場合、DocumentStore は破棄されません。

パラメーターをオブジェクトのコンストラクターに渡す、オブジェクト初期化子を使用する代わりに using ステートメント内でプロパティを設定する、try/finally ブロックを使用するなど、いくつかの回避策があります。

于 2012-04-12T16:15:26.320 に答える
1

まず、shards渡した には、破棄されたとnew ShardedDocumentStore()が含まれています。これにより、問題が発生する可能性が高くなります。docStore1docStore2

また、catch ステートメントでは、docStores既に破棄されている可能性のある を破棄します。

最後に、ShardedDocumentStore返された は、返されたときに (使用によって) 破棄されているため、呼び出し元が使用できなくなる可能性があります。

また、ShardedDocumentStore(GitHub で) をざっと見たところ、そのdocStores. つまり、あなたはそれを扱うべきではありません。

コードを次のように変更します。

private static IDocumentStore GetRavenDatabase()
{
    ShardedDocumentStore documentStore = null;
    var docStore1 = null;
    var docStore2 = null;

    try
    {
        Shards shards = new Shards();
        docStore1 = new DocumentStore { Url = ConfigurationManager.AppSettings["RavenShard1"] };
        shards.Add(docStore1);
        docStore2 = new DocumentStore { Url = ConfigurationManager.AppSettings["RavenShard2"] };
        shards.Add(docStore2);

        documentStore = new ShardedDocumentStore(new ShardStrategy(), shards);
        documentStore.Initialize();

        IndexCreation.CreateIndexes(typeof(RavenDataAccess).Assembly, documentStore);

        return documentStore;
    }
    catch
    {
        if (documentStore != null)
        {
            documentStore.Dispose();
        }
        else
        {
            if (docStore2 != null) docStore2.Dispose();
            if (docStore1 != null) docStore1.Dispose();
        }
        throw;
    }
}

GetRavenDatabase()...そして、返された の処理を​​呼び出し元に処理させIDocumentStoreます。

于 2012-04-12T14:15:26.577 に答える