2017-06-30 4 views
-1

少なくとも3GBのデータを含むAPI URLからデータを取得しようとしています(エンタープライズレベルなので)。これをSQL Serverのテーブルに挿入しようとしています。 「プログラムの実行を続行するにはメモリが不足しています」というエラーが表示されます。私は、文字列のみ、以下は動作しません理由ですデータの2GBの最大を含めることができることを承知している:少なくとも3GBのデータのHttpWebRequestまたはHttpWebClient

string data = client.DownloadString(siteUrl) nor 
string data = readStream.ReadToEnd() 

私たちは、地域によってデータをフィルタしますクエリパラメータを持っているアイデアを思い付いたが、この特定の領域が2GBのデータを超えると失敗します。では、API URLからデータ全体を得ることができる他の方法はありますか?

編集 私たちが現在持っているのは、データをC#の文字列オブジェクトに格納することです。

string data = client.DownloadString(siteUrl) 

データをデシリアライズして、次の手順で必要な要素を除外することができます。

JsonConvert.DeserializeObject<Dictionary<string, object>>(data) 

返されたAPIはデータのリストを返さないため、データを取得する場所でstartElementを定義する必要があります。

List<Dictionary<string, string>> arrayOfData = (List<Dictionary<string, string>>)(data[startElement] as Newtonsoft.Json.Linq.JArray).ToObject(typeof(List<Dictionary<string, string>>)); 

それは次いでSQLプロバイダによってデータベースに挿入される一覧>にそれを格納するためのSQLの列のマッピングデータと一致するarrayOfData.Countを通して反復します。以下は、データ構造の例です(実際のデータは機密情報なので)

{"href": "someUrl"、 "limit": "1"、 "records":[{"columnA": "1" 「columnB」:「2」、「columnC」:「3」}]}

は、問題は、データ3GBのは、文字列はので、私は聞いてるのよ処理するには多すぎるので、私が処理を行うことはできません私はそれをファイルに保存することができますが、データはそのまま挿入するのが難しくなります。

+0

ストリームで作業する必要があります。 'ReadToEnd'を呼び出さないでください。 – NtFreX

+0

@ NtFreXしかし、テーブルに挿入するためにデータを解析するにはどうしたらいいですか? –

+0

APIを管理できますか? –

答えて

0

:deliminatorに達した(正規表現を使用して)まで、ストリームからチャンクに読むことができる

(等}、配列内のオブジェクトの終了)、及びデシリアライズとプロセス1(または固定数)のオブジェクトを一度に読み取ってからさらに読む

だから私はやった!興味のある人には、ここで手順は次のとおりです。

  • 代わりの文字列client.DownloadString(siteUrl)にデータの大きな塊を格納し、データをファイルclient.DownloadFile(siteUrl, "data.json")にダウンロードされました。
  • using (StreamReader sr = new StreamReader(@"E:Debug\data.json"))から各文字を読み取るためにStreamReaderを使用しました。
  • "["に遭遇した場合、ダウンロードしたファイルから各文字を読み込んで保存する方法を作成しました。
  • 各文字をList<char>に格納し、新しい文字列new String(chars.ToArray())を作成します(「}」に当てはまる場合 - 1の「{}」は1つの有効なレコードに相当します)。
  • JSONは文字列をJsonConvert.DeserializeObject<Dictionary<string, string>>(record)
  • でデシリアライズします。データを挿入したSQL Serverテーブルの各列にデータをマッピングします。
  • 次のレコードを処理するためにデータを挿入した後にList<char>をクリアします。

この処理では、一度に1つのレコードしか保存されません。それは機能しますが、仕上げには時間がかかります。これを処理するより良い方法があれば教えてください!

0

代わりにファイルに書き込みます。例えば

using (var file = File.OpenWrite(@"c:\temp\foo.dat")) 
{ 
    readStream.CopyTo(file); 
} 
+0

申し訳ありません私はちょうど私の質問を編集しました。私はファイルとしてデータを保存することができますが、私の問題はC#でオブジェクトに格納することができないので、データを解析してSQL Serverのテーブルに挿入する方法にあります。 –

+0

ストリームからの読み取りを開始し、レコードを解析してSQL Serverを読み込みます。多くのデータをロードするには、SqlBulkCopyを使用します。 –

+0

ありがとうございますが、これは私の問題ではうまくいかないと思います。私は私の質問に編集セクションを追加しました。 –

0

あなたは64 OS上で動作し、理想的な世界でAPIが変更されるべき2G

<runtime> 
    <gcAllowVeryLargeObjects enabled="true" />  
</runtime> 

のメモリの制限を解除します。このアプリケーションの設定よりも、.NET 4.5以降を使用することができる場合その多くのデータを返す可能性がある場合はページングを実装します。コメントからイゴールによって示唆されるよう

+0

これを試してみましょう! –

+0

どうやってあなたに行きましたか? –

+1

ありがとうございます。残念ながら、うまくいきませんでした。私はIgorがコメントに示唆した私のために働いた答えを投稿しました。 –

関連する問題