更有效的方法来迭代我的数据(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 还是其他任何格式。这只是要求难以发现的错误和注入,因为您无法控制数据或表名。例如,如果您的数据包含!&lt;&gt;,会发生什么情况?

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 中准确地迭代每个键一次的有效方法

哪个更有效,for-each 循环还是迭代器?

一种更有效的方法来总结 postgres 中列之间的差异?

在 Java Spark 中迭代大型数据集的最快且有效的方法

为啥#map 比#each 更有效?

在 SYCL 中使用一个缓冲区还是多个缓冲区更有效?