2016-03-29 27 views
2

私はUR1を介して3GBのXMLファイルを読み込み、すべてのジョブをデータセットに格納しようとしています。 XMLは次のようになります。DataSetに大きなXMLをロードする(OutOfMemory Exception)

<?xml version="1.0"?> 
    <feed total="1621473"> 
     <job> 
     <title><![CDATA[Certified Medical Assistant]]></title> 
     <date>2016-03-25 14:19:38</date> 
     <referencenumber>2089677765</referencenumber> 
     <url><![CDATA[http://www.jobs2careers.com/click.php?id=2089677765.1347]]></url> 
     <company><![CDATA[Broadway Medical Clinic]]></company> 
     <city>Portland</city> 
     <state>OR</state> 
     <zip>97213</zip> 
    </job> 
    <job> 
     <title><![CDATA[Certified Medical Assistant]]></title> 
     <date>2016-03-25 14:19:38</date> 
     <referencenumber>2089677765</referencenumber> 
     <url><![CDATA[http://www.jobs2careers.com/click.php?id=2089677765.1347]]></url> 
     <company><![CDATA[Broadway Medical Clinic]]></company> 
     <city>Portland</city> 
     <state>OR</state> 
     <zip>97213</zip> 
    </job> 
    </feed> 

これは私のコード

XmlDocument doc = new XmlDocument(); 
      doc.Load(url); 
      DataSet ds = new DataSet(); 
      XmlNodeReader xmlReader = new XmlNodeReader(doc); 

      while (xmlReader.ReadToFollowing("job")) 
      { 
       ds.ReadXml(xmlReader); 
      } 

ですが、私は、バインドされた例外のうちのメモリを得ました。 Google で検索し、これを見つけました:

DataSet ds = new DataSet(); 
     FileStream filestream = File.OpenRead(url); 
     BufferedStream buffered = new BufferedStream(filestream); 
     ds.ReadXml(buffered); 

まだ同じ例外があります。私はXmlTextReaderについても読んでいますが、私の場合はどのように使用するのか分かりません。 なぜ例外が発生しているのかわかりますが、その克服方法はわかりません。

+0

例外の詳細はなんですか? 私はそれが 'OutOfMemoryException'を投げているXmlDocumentかもしれないと思う。なぜなら、大規模なXMLファイルを生成するためのコードをまとめて、十分なデータを生成する前に、私が構築したXmlDocumentオブジェクトを投げているからです。おそらく、ノードの内部コレクション({System.Collections.ListDictionaryInternal.NodeKeyValueCollection})に関連しています。 – Stringfellow

+0

出力は何ですか?私は "すべての仕事が苦しい"と理解していません。 –

+0

@MichaelKay:私の悪い、編集された。私はすべてのジョブをデータセットに保存したいので、後ですべてをデータベーステーブルに保存することができます。 – Iman

答えて

1

代わりのデータセットまたは他の容器に、ファイル全体をロードしようと、どのようにロードバッチについてを試してみて、バッチを保持しているものは何でもので、データベースに各バッチの書き込みがクリアすることができます毎回?

方法:DataSetを使用して大規模なXML文書の変換ストリーミング https://msdn.microsoft.com/en-us/library/bb387013.aspx

 List<XElement> jobs = new List<XElement>(); 
     using (XmlReader reader = XmlReader.Create(filePath)) 
     { 
      XElement job; 
      reader.MoveToContent(); 
      while (reader.Read()) 
      { 
       if ((reader.NodeType == XmlNodeType.Element) && (reader.Name == "job")) 
       { 
        job = XElement.ReadFrom(reader) as XElement; 
        jobs.Add(job); 

        if (jobs.Count >= 1000) 
        { 
         // TODO: write batch to database 
         jobs.Clear(); 
        } 
       } 
      } 

      if (jobs.Count > 0) 
      { 
       // TODO: write remainder to database 
       jobs.Clear(); 
      } 

     } 

代替を行います。

 DataSet ds = new DataSet(); 
     using (XmlReader reader = XmlReader.Create(filePath)) 
     { 
      reader.MoveToContent(); 
      while (reader.Read()) 
      { 
       if ((reader.NodeType == XmlNodeType.Element) && (reader.Name == "job")) 
       { 
        ds.ReadXml(reader); 

        DataTable dt = ds.Tables["job"]; 
        if (dt.Rows.Count >= 1000) 
        { 
         // TODO: write batch to database 
         dt.Rows.Clear(); 
        } 
       } 
      } 

      if (ds.Tables["job"].Rows.Count > 0) 
      { 
       // TODO: write remainder to database 
       ds.Tables["job"].Rows.Clear(); 
      } 
     } 
+0

ありがとうございました。このコードを使用して、データセットにデータを取り込む方法は? – Iman

+0

私は別の方法を追加しました。それはあなたがDataSetをロードすることを意味していますか? メモリの問題が発生することなく、3 GBファイル全体をDataSetにロードできるかどうかはわかりません。また、バッチ処理では、処理が途中で失敗した場合に「再開」シナリオを有効にすることができます。 – Stringfellow

+0

データセットに2行ずつデータが取り込まれ、その後に最初のif文がfalseになると、何らかの理由がありますか?まだそれに取り組んでいます。あなたのソリューションはしっかりしていると思います。 – Iman

0

doc.Load()はファイル全体を読み込んでエラーを出します。 XmlNodeReaderは本当にあなたのために何もしません。この

using System; 
 
using System.Collections.Generic; 
 
using System.Linq; 
 
using System.Text; 
 
using System.Xml; 
 
using System.Xml.Linq; 
 
using System.Data; 
 

 
namespace ConsoleApplication1 
 
{ 
 
    class Program 
 
    { 
 
     const string url = @"c:\temp\test.xml"; 
 
     static void Main(string[] args) 
 
     { 
 
      int count = 0; 
 
      DataSet ds = new DataSet(); 
 
      XmlReader xmlReader = XmlReader.Create(url); 
 
      xmlReader.MoveToContent(); 
 
      try 
 
      { 
 
       while (!xmlReader.EOF) 
 
       { 
 
        count++; 
 
        xmlReader.ReadToFollowing("job"); 
 
        if (!xmlReader.EOF) 
 
        { 
 
         ds.ReadXml(xmlReader); 
 
        } 
 
       } 
 
      } 
 
      catch (Exception ex) 
 
      { 
 
       Console.WriteLine("Count : {0}", count); 
 
       Console.ReadLine(); 
 
      } 
 
      
 
     } 
 
    } 
 

 
}

+0

ds.ReadXml()にSystem.OutOfMemoryExceptionがまだ残っています – Iman

+0

いくつかの誤植を削除するコードを更新しました。問題が修正されるかどうかは不明です。例外の前に読み込まれたジョブ要素の行数は分かりますか? – jdweng

+0

ありがとうございました。同じ例外はありません。私はそれをデバッグしようとしましたが、それは私に何行が読み込まれているかを知らせません。私は、xmlファイルを塊に分割し、それを一つずつ読んだり、バッファを介してファイルを読み込んで、ファイル全体を一度に読み込まないようにする方法がなければならないと思います。私はそれを達成する方法を知りません。 – Iman

関連する問題