我目前正在将一些Access数据库转换为Xml文件。我之前已经做过这个,并且还保存了以前项目的代码。然而,这段代码不能让我随心所欲地构建xml,而这正是我这次需要做的。我正在使用
阅读关于XDocument如何工作的资料告诉我,
以下是读取和写入来自Access到Xml的部分内容,请查看并看看是否有任何方法可以解决这个问题。转换一个具有27列和12,256行的数据库需要近30分钟,而一个仅有500行的较小数据库则需要大约5秒钟。
这是我旧转换器的代码。无论数据库的大小如何,该代码都不会受到太大影响,12556个数据库只需要一秒钟即可转换。可能有一种方法可以将这两个合并吗?
XDocument
和for
循环实现这一点,但在几千行数据后,速度变得非常缓慢。阅读关于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);
}
}
这是我旧转换器的代码。无论数据库的大小如何,该代码都不会受到太大影响,12556个数据库只需要一秒钟即可转换。可能有一种方法可以将这两个合并吗?
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秒钟。
更新:好的,我经过周末回来了,现在我在代码中做了一个小调整,通过在一个循环中用值填充一个锯齿形数组,并在另一个循环中将其写入以分离读取和写入。这证明了我的理论是错误的,实际上是读取需要花费大量时间。有什么办法可以在循环内填充数组而不需要访问数据库吗?
更新2:在切换到DataReader.Read()
循环并立即收集所有数据后,这就是最终结果。
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);
}
}