我目前正在將許多Access數據庫轉換爲Xml文件。我之前完成了這個工作,而且我仍然擁有以前項目的代碼。然而,這段代碼不會讓我按照自己的喜好來構造xml,這是我需要做的這一次。我使用XDocument
和for
-loops來實現這個目標,但是在幾行1000行數據後它變得非常慢。爲什麼這個代碼變慢?
瞭解XDocument的工作原理告訴我,XElement.Add
實際上會複製整個xml代碼,並在將所有內容粘貼到文件中時添加新元素。如果這是真的,那麼這可能是問題所在。
這是從Access訪問Xml讀取和寫入數據的部分,看看是否有任何保存方式。使用27列和12 256行轉換數據庫需要將近30分鐘,而只有500行的較小數據庫需要大約5秒。
private void ReadWrite(string file)
{
using (_Connection = new OleDbConnection(string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Mode=12;Data Source={0}", pathAccess)))
{
_Connection.Open();
//Gives me values from the AccessDB: tableName, columnName, colCount, rowCount and listOfTimeStamps.
GetValues(pathAccess);
XDocument doc = new XDocument(new XDeclaration("1.0", "utf-8", "true"), new XElement(tableName));
for (int rowInt = 0; rowInt < rowCount; rowInt++)
{
XElement item = new XElement("Item", new XAttribute("Time", listOfTimestamps[rowInt].ToString().Replace(" ", "_")));
doc.Root.Add(item);
//colCount"-1" prevents the timestamp from beeing written again.
for (int colInt = 0; colInt < colCount - 1; colInt++)
{
using (OleDbCommand cmnd = new OleDbCommand(string.Format("SELECT {0} FROM {1} Where TimeStamp = #{2}#", columnName[colInt] , tableName, listOfTimestamps[rowInt]), _Connection))
{
XElement value = new XElement(columnName[colInt], cmnd.ExecuteScalar().ToString());
item.Add(value);
}
}
//Updates progressbar
backgroundWorker1.ReportProgress(rowInt);
}
backgroundWorker1.ReportProgress(0);
doc.Save(file);
}
}
這是我的舊轉換器的代碼。這段代碼幾乎不受數據庫大小的影響,12 556數據庫只需要一秒鐘的時間進行轉換。那麼可能有合併這兩者的方法嗎?
public void ReadWrite2(string file)
{
DataSet dataSet = new DataSet();
using (_Connection = new OleDbConnection(string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Mode=12;Data Source={0}", file)))
{
_Connection.Open();
DataTable schemaTable = _Connection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
foreach (DataRow dataTableRow in schemaTable.Rows)
{
string tableName = dataTableRow["Table_Name"].ToString();
DataTable dataTable = dataSet.Tables.Add(tableName);
using (OleDbCommand readRows = new OleDbCommand("SELECT * from " + tableName, _Connection))
{
OleDbDataAdapter adapter = new OleDbDataAdapter(readRows);
adapter.Fill(dataTable);
}
}
}
dataSet.WriteXml(file.Replace(".mdb", ".xml"));
}
編輯:只是爲了澄清,因爲它執行的應用程序變慢。正如前500個無論數據庫有多大都需要5秒。
UPDATE:好了,所以我特地在週末回來後,現在我在代碼中做了一個小的調整,以單獨的閱讀和寫作的填充值的鋸齒形陣列中的一個循環,並以書面形式另一個。這已經證明我的理論是錯誤的,事實上,閱讀需要很長時間。有關如何用數值填充數組而不碰循環內數據庫的想法?
UPDATE2:這是在切換到DataReader.Read()
-loop並立即收集所有數據後的最終結果。
public void ReadWrite3(string Save, string Load)
{
using (_Connection = new OleDbConnection(string.Format("Provider=Microsoft.ACE.OLEDB.12.0;Mode=12;Data Source={0}", Load)))
{
_Connection.Open();
GetValues(_Connection);
_Command = new OleDbCommand(String.Format("SELECT {0} FROM {1}", strColumns, tables), _Connection);
XDocument doc = new XDocument(new XDeclaration("1.0", "utf-8", "true"), new XElement("plmslog", new XAttribute("machineid", root)));
using (_DataReader = _Command.ExecuteReader())
{
for (int rowInt = 0; _DataReader.Read(); rowInt++)
{
for (int logInt = 0; logInt < colCount; logInt++)
{
XElement log = new XElement("log");
doc.Root.Add(log);
elementValues = updateElementValues(rowInt, logInt);
for (int valInt = 0; valInt < elements.Length; valInt++)
{
XElement value = new XElement(elements[valInt], elementValues[valInt]);
log.Add(value);
}
}
}
}
doc.Save(Save);
}
}
你有沒有試過分析你的代碼,看看瓶頸在哪裏? – ChrisBint 2013-04-05 08:16:09
@ChrisBint不,我沒有。我可以在沒有任何第三方工具或軟件的情況下做這些嗎? – 2013-04-05 08:45:14