2016-12-05 4 views
1

10000レコードをAzureテーブルストレージに挿入しようとしています。私はそれを達成するためにExecuteAsync()を使用していますが、何とか約7500レコードが挿入され、残りのレコードが失われます。私は意図的にを使用していません。キーワードを待っています。結果を待たずにテーブルに保存したいからです。以下は私のコードスニペットです。AzureテーブルストレージのExecuteAsync()がすべてのレコードを挿入できません

private static async void ConfigureAzureStorageTable() 
    { 
     CloudStorageAccount storageAccount = 
      CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString")); 
     CloudTableClient tableClient = storageAccount.CreateCloudTableClient(); 
     TableResult result = new TableResult(); 
     CloudTable table = tableClient.GetTableReference("test"); 
     table.CreateIfNotExists(); 

     for (int i = 0; i < 10000; i++) 
     { 
      var verifyVariableEntityObject = new VerifyVariableEntity() 
      { 
       ConsumerId = String.Format("{0}", i), 
       Score = String.Format("{0}", i * 2 + 2), 
       PartitionKey = String.Format("{0}", i), 
       RowKey = String.Format("{0}", i * 2 + 2) 
      }; 
      TableOperation insertOperation = TableOperation.Insert(verifyVariableEntityObject); 
      try 
      { 
       table.ExecuteAsync(insertOperation); 
      } 
      catch (Exception e) 
      { 

       Console.WriteLine(e.Message); 
      } 
     } 
    } 

このメソッドの使用に間違いがありますか?

+1

終了するのを待たずに終了できない場合があります(特にプロセスが終了した場合)。そして、あなたはどんな誤りについても知りません。 – SLaks

+0

それが完了するのを待たなければ、おそらく終わらないでしょう! – DavidG

+0

この問題は解決しましたか? Azure Table Storageにレコードを挿入すると、コンソールアプリケーション内で詳細な例外を検出し、Fiddler経由でネットワークパッケージを取得できます。 –

答えて

3

お客様await table.ExecuteAsync()になります。これは、ConfigureAzureStorageTable()がその時点で呼び出し元に制御を返し、実行を継続できることを意味します。

あなたが質問でそれを持っている方法、ConfigureAzureStorageTable()table.ExecuteAsync()への呼び出しと終了を過ぎて続けることが起こっている、とtable.ExecuteAsync()タスクがまだ完了していない間、tableのようなものは、スコープの外に移動します。

async voidをSOと他の場所で使用する場合には注意が必要です。あなたはほぼ確実に使用したい - 1に加え:あなたは同じように簡単に

編集 など、async Taskとしてあなたの方法を持っているが、まだ、発信者でそれを待っていないが、きれいな終了のための周りに返さTaskを保つことができますawaitにはConfigureAwait(false)があります。コンテキストを保存する必要はありません。このblog postには、それとasyncに関する一般的なガイドラインがいくつかあります。

1

を使用して一度にN個のインサートのバッチを実行するのはどうですか?

private const int BatchSize = 100; 

private static async void ConfigureAzureStorageTable() 
{ 
    CloudStorageAccount storageAccount = 
     CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString")); 
    CloudTableClient tableClient = storageAccount.CreateCloudTableClient(); 
    TableResult result = new TableResult(); 
    CloudTable table = tableClient.GetTableReference("test"); 
    table.CreateIfNotExists(); 

    var batchOperation = new TableBatchOperation(); 

    for (int i = 0; i < 10000; i++) 
    { 
     var verifyVariableEntityObject = new VerifyVariableEntity() 
     { 
      ConsumerId = String.Format("{0}", i), 
      Score = String.Format("{0}", i * 2 + 2), 
      PartitionKey = String.Format("{0}", i), 
      RowKey = String.Format("{0}", i * 2 + 2) 
     }; 
     TableOperation insertOperation = TableOperation.Insert(verifyVariableEntityObject); 
     batchOperation.Add(insertOperation); 

     if (batchOperation.Count >= BatchSize) 
     { 
      try 
      { 
       await table.ExecuteBatchAsync(batchOperation); 
       batchOperation = new TableBatchOperation(); 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine(e.Message); 
      } 
     } 
    } 

    if(batchOperation.Count > 0) 
    { 
     try 
     { 
      await table.ExecuteBatchAsync(batchOperation); 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine(e.Message); 
     } 
    } 
} 

必要に応じてBatchSizeを調整できます。小さな免責事項:私はこれを実行しようとしなかったが、それは動作するはずです。

しかし、私は助けることはできませんが、あなたの機能はなぜですかasync void?これは、イベントハンドラやインターフェイスを決めることができない同様のもののために予約する必要があります。ほとんどの場合、タスクを返す必要があります。呼び出し元はこの関数で発生する例外をキャッチすることができないためです。

0

async voidは、イベントハンドラでない限り、良い方法ではありません。

https://msdn.microsoft.com/en-us/magazine/jj991977.aspx

あなたはAzureテーブルストレージに多くのレコードを挿入する場合は、バッチ挿入が最善の策です。

https://msdn.microsoft.com/en-us/library/azure/microsoft.windowsazure.storage.table.tablebatchoperation.aspx

それはバッチ当たり100のテーブル操作の制限があることに注意してください。

1

お客様の要件に応じて、私はCloudTable.ExecuteAsyncCloudTable.ExecuteBatchAsyncを使用して自分のシナリオをテストしました。 Azure Table Storageにレコードを挿入するためのCloudTable.ExecuteBatchAsyncのコードスニペットを参照してください。

プログラム。CSメイン

class Program 
{ 
    static void Main(string[] args) 
    { 
     CloudStorageAccount storageAccount = 
      CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("StorageConnectionString")); 
     CloudTableClient tableClient = storageAccount.CreateCloudTableClient(); 
     TableResult result = new TableResult(); 
     CloudTable table = tableClient.GetTableReference("test"); 
     table.CreateIfNotExists(); 

     //Generate records to be inserted into Azure Table Storage 
     var entities = Enumerable.Range(1, 10000).Select(i => new VerifyVariableEntity() 
     { 
      ConsumerId = String.Format("{0}", i), 
      Score = String.Format("{0}", i * 2 + 2), 
      PartitionKey = String.Format("{0}", i), 
      RowKey = String.Format("{0}", i * 2 + 2) 
     }); 

     //Group records by PartitionKey and prepare for executing batch operations 
     var batches = TableBatchHelper<VerifyVariableEntity>.GetBatches(entities); 

     //Execute batch operations in parallel 
     Parallel.ForEach(batches, new ParallelOptions() 
     { 
      MaxDegreeOfParallelism = 5 
     }, (batchOperation) => 
     { 
      try 
      { 
       table.ExecuteBatch(batchOperation); 
       Console.WriteLine("Writing {0} records", batchOperation.Count); 
      } 
      catch (Exception ex) 
      { 
       Console.WriteLine("ExecuteBatch throw a exception:" + ex.Message); 
      } 
     }); 
     Console.WriteLine("Done!"); 
     Console.WriteLine("Press any key to exit..."); 
     Console.ReadKey(); 
    } 
} 

TableBatchHelper.cs

public class TableBatchHelper<T> where T : ITableEntity 
{ 
    const int batchMaxSize = 100; 

    public static IEnumerable<TableBatchOperation> GetBatches(IEnumerable<T> items) 
    { 
     var list = new List<TableBatchOperation>(); 
     var partitionGroups = items.GroupBy(arg => arg.PartitionKey).ToArray(); 
     foreach (var group in partitionGroups) 
     { 
      T[] groupList = group.ToArray(); 
      int offSet = batchMaxSize; 
      T[] entities = groupList.Take(offSet).ToArray(); 
      while (entities.Any()) 
      { 
       var tableBatchOperation = new TableBatchOperation(); 
       foreach (var entity in entities) 
       { 
        tableBatchOperation.Add(TableOperation.InsertOrReplace(entity)); 
       } 
       list.Add(tableBatchOperation); 
       entities = groupList.Skip(offSet).Take(batchMaxSize).ToArray(); 
       offSet += batchMaxSize; 
      } 
     } 
     return list; 
    } 
} 

注:エンティティのバッチを挿入については、公式documentで述べたように:

単一バッチ操作ができます entiネクタイ。

一括処理のすべてのエンティティには、の同じパーティションキーが必要です。

要約すると、あなたの側で動作するかどうかを確認してください。また、コンソールアプリケーション内で詳細な例外をキャプチャし、Azureテーブルストレージにレコードを挿入するときにHTTPエラー要求をキャッチするためにFiddler経由でHTTP要求を取得することもできます。

関連する問題