更有效的方法来迭代我的数据(DbReader/DataSet)
Posted
技术标签:
【中文标题】更有效的方法来迭代我的数据(DbReader/DataSet)【英文标题】:More efficient way to iterate on my data (DbReader/DataSet) 【发布时间】:2021-11-09 19:47:38 【问题描述】:我正在使用 C# 开发一个项目,该项目将数据库表转换为具有 base64 编码内容的 XML 文件。请多多包涵,因为 C# 不是我的日常编程语言。
我想出的代码是这样的:
OdbcCommand DbCommand = DbConnection.CreateCommand();
DbCommand.CommandText = "SELECT * FROM " + dbTable;
OdbcDataReader DbReader = DbCommand.ExecuteReader();
int fCount = DbReader.FieldCount;
string[] colnames = new string[fCount];
output += "<" + dbTable + ">\n";
for (int i = 0; i < fCount; i++)
string fName = DbReader.GetName(i);
colnames[i] = fName.ToString();
while (DbReader.Read())
output += "\t<export_row>\n";
for (int i = 0; i < fCount; i++)
string col = "";
try
col = DbReader.GetString(i);
catch (Exception)
if (col.ToString().Length > 0 || i == 0)
output += "\t\t<" + colnames[i] + ">" + Base64Encode(col).ToString() + "</" + colnames[i] + ">\n"; ;
output += "\t</export_row>\n";
output += "</" + dbTable + ">\n";
问题是,即使使用相对较小的表,这也会导致应用程序阻塞并运行极其缓慢。明显的线索是每一行都涉及大量的迭代,所以我一直在寻找解决这个问题的方法。我尝试过使用 DataSet,它似乎稍微提高了性能,但还不够显着。
connection.Open();
adapter.Fill(dataSet);
output += "<" + dbTable + ">\n";
foreach (DataTable table in dataSet.Tables)
foreach (DataRow row in table.Rows)
output += "\t<export_row>\n";
foreach (DataColumn column in table.Columns)
output += "\t\t<" + column.ToString() + ">" + Base64Encode(row[column].ToString()).ToString() + "</" + column.ToString() + ">\n"; ;
output += "\t</export_row>\n";
output += "</" + dbTable + ">\n";
但是,问题仍然存在,除了每次都遍历所有列之外别无他法。这引出了一个问题:没有更有效的方法来做到这一点吗?我不会为每个表都建立一个模型,因为这个数据库中有数百个表,而强大的功能就是以这种方式传输数据的灵活性。
有人可以帮助我,或指出正确的方向吗?例如,有没有办法同时提取列和值?如: foreach(row as key => value) 什么的。这将大大减少所需的迭代次数。
提前感谢您的考虑!一定有什么(明显的)我错过了。
【问题讨论】:
查看 DataSet 的GetXML()
和 WriteXML()
方法。 docs.microsoft.com/en-us/visualstudio/data-tools/…
自己编写 XML 不是正确的方法。 C# 有很多 XML 函数,包括直接将 DataSet 转换为 XML。
见***.com/questions/16768263/…
你也应该使用StringBuilder
,我相信这会有所帮助。
您到底使用哪个 DBMS?有些具有内置的 XML 创建功能。请参阅 Sql Server 中的FOR XML。
【参考方案1】:
关键始终是不要自己编写文本格式的格式,无论是 html、JSON、XML、YAML 还是其他任何格式。这只是要求难以发现的错误和注入,因为您无法控制数据或表名。例如,如果您的数据包含!
、<
或>
,会发生什么情况?
C# 有许多内置的 XML 工具,为您完成格式化的 SQL 也是如此。使用哪一种取决于您的其他要求或偏好。
SqlCommand.ExecuteXmlReader string cmd = "SELECT * FROM " + myTable + " FOR XML AUTO";
using (SqlCommand k = new SqlCommand(cmd, c))
c.Open();
XmlReader xml = k.ExecuteXmlReader();
Console.WriteLine(xml);
c.Close();
DataTable.WriteXml
string ConString = "your connection string";
string CmdString = "SELECT * FROM " + myTable;
SqlConnection con;
SqlCommand cmd;
SqlDataAdapter sda;
DataTable dt;
using (con = new SqlConnection(ConString))
cmd = new SqlCommand(CmdString, con);
con.Open();
dt = new DataTable(tableName);
sda = new SqlDataAdapter(cmd);
sda.Fill(dt);
dt.WriteXml(tableName + ".xml");
con.Close();
DataSet.GetXml()
// Create a DataSet with one table containing
// two columns and 10 rows.
DataSet dataSet = new DataSet("dataSet");
DataTable table = dataSet.Tables.Add("Items");
table.Columns.Add("id", typeof(int));
table.Columns.Add("Item", typeof(string));
// Add ten rows.
DataRow row;
for(int i = 0; i <10;i++)
row = table.NewRow();
row["id"]= i;
row["Item"]= "Item" + i;
table.Rows.Add(row);
// Display the DataSet contents as XML.
Console.WriteLine(dataSet.GetXml());
【讨论】:
感谢您的评论!我完全同意您的说法,即自己生成 XML 通常不是最好的解决方案。到目前为止,DataSet.GetXml() 似乎几乎完全符合要求。我面临的问题是我需要对数据库进行 base64 编码,因为我还将包括文件内容(如图像),并且我想确保没有任何东西会破坏 XML,或者更确切地说,没有东西会破坏 XML 阅读器在数据传输的另一端。我一直试图从数据库中获取base64编码,但无济于事。你知道有什么方法可以在这种情况下工作吗? 我从未尝试过使用 CML 进行 base64 编码,但有很多示例。查看***.com/questions/17835928/… 和***.com/questions/23498426/…。至于检查 XML 的正确性。我以前使用过 XSD,它们工作得很好***.com/questions/751511/…,但我有一个特定的文档要验证。如果遇到问题,您可能想在 SO 上发布另一个问题。 感谢您的回复!最后我决定更改软件的接收端以便能够使用您的建议。我仍然对 base64 编码图像使用“旧”方法,但是对查询进行了一些更改,并使用了一种单独的方法来发送这些数据,我让它工作得很好。我对性能的巨大提升感到非常高兴。谢谢!以上是关于更有效的方法来迭代我的数据(DbReader/DataSet)的主要内容,如果未能解决你的问题,请参考以下文章
在 unordered_multimap 中准确地迭代每个键一次的有效方法