web-dev-qa-db-ja.com

タイプ「System.OutOfMemoryException」の例外がスローされました

基本的に、私はEntityFrameworkを使用して巨大なデータベースをクエリします。文字列リストを返し、それをテキストファイルに記録したいと思います。

List<string> logFilePathFileName = new List<string>();
var query = from c in DBContext.MyTable where condition = something select c;
foreach (var result in query)
{
    filePath = result.FilePath;
    fileName = result.FileName;
    string temp = filePath + "." + fileName;
    logFilePathFileName.Add(temp);
    if(logFilePathFileName.Count %1000 ==0)
        Console.WriteLine(temp+"."+logFilePathFileName.Count);
}

ただし、logFilePathFileName.Count=397000。例外は次のとおりです。

タイプ「System.OutOfMemoryException」の例外がスローされました。

System.Data.Entity.dllでタイプ「System.OutOfMemoryException」の最初のチャンスの例外が発生しました

更新:

別のクエリを使用したいのですが、上位1000を選択してリストに追加しますが、1000以降は何がわかりませんか?

7
user1108948

テキストファイルに書き込むだけでデータをList<string>に収集するのはなぜですか?

あなたもそうかもしれません:

  • テキストファイルを開きます。
  • レコードを繰り返し処理し、各文字列をテキストファイルに追加します(文字列をメモリに保存せずに)。
  • テキストファイルをフラッシュして閉じます。

これらすべての文字列を不必要にメモリに保持することがないため、必要なメモリは現在よりはるかに少なくなります。

3
Roy Dictus

おそらくメモリ用にいくつかのvmargsを設定する必要があります!また...リストに保持せずにファイルに直接書き込むことを検討してください

1
Bob Flannigon

Roy Dictusの言うことは、最善の方法に聞こえます。また、クエリに制限を追加してみることもできます。したがって、データベースの結果はそれほど大きくなりません。

情報: エンティティフレームワークによるクエリサイズの制限

1

データベースからリストにすべてのレコードを読み取るべきではありません。大量のメモリが必要でした。レコードの読み取りとファイルへの書き込みを組み合わせます。たとえば、dbから1000レコードを読み取り、それらをテキストファイルに保存(追加)し、使用済みメモリをクリアし(list.Clear())、新しいレコードを続行します。

0
Warr

以前は、使用したgcリストと同様にVS c ++でgcarraylistを使用して、小規模および中間のデータセットでfinを機能させていましたが、Big Datを使用すると、同じ問題「System.OutOfMemoryException」がスローされました。これらのgcsのサイズは2GBを超えることはできず、ビッグデータでは非効率になるため、同じ機能、動的な増加、インデックスによる取得を提供する独自のリンクリストを作成しました。基本的に、これは通常のリンクリストクラスであり、内部の動的配列は、インデックスによるデータの取得を提供し、スペースを複製しますが、配列の更新後にリンクリストを削除できます。動的配列のみを保持する必要がない場合、これで問題が解決します。コードを参照してください:

struct LinkedNode
{
    long data;
    LinkedNode* next;
};


class LinkedList
{
public:
    LinkedList();
    ~LinkedList();
    LinkedNode* head;
    long Count;
    long * Data;
    void add(long data);
    void update();
    //long get(long index);
};

LinkedList::LinkedList(){
    this->Count = 0;
    this->head = NULL;
}

LinkedList::~LinkedList(){
    LinkedNode * temp; 
    while(head){
        temp= this->head ;
        head = head->next;
        delete temp;
    }
    if (Data)
        delete [] Data; Data=NULL;
}

void LinkedList::add  (long data){
    LinkedNode * node = new LinkedNode();
    node->data = data;
    node->next = this->head;
    this->head = node;
    this->Count++;}

void LinkedList::update(){
    this->Data= new long[this->Count];
    long i = 0;
    LinkedNode * node =this->head;
    while(node){
        this->Data[i]=node->data;
        node = node->next;
        i++;
    }
}

これを使用する場合は、私の作品を参照してください https://www.liebertpub.com/doi/10.1089/big.2018.0064

0
Ahmad Hassanat

StackOverflowに関する他のいくつかのトピックから、EntityFrameworkはそのようなバルクデータを処理するように設計されていないことを読みました。 EFはコンテキスト内のすべてのデータをキャッシュ/追跡し、大量のデータの場合に例外を引き起こします。オプションは、SQLを直接使用するか、レコードを小さなセットに分割することです。

0
Abbas