合并的数据行不会在数据库中更新,但添加的数据行会。为啥?

Posted

技术标签:

【中文标题】合并的数据行不会在数据库中更新,但添加的数据行会。为啥?【英文标题】:Merged DataRows are not Updated in the database but Added DataRows are. Why?合并的数据行不会在数据库中更新,但添加的数据行会。为什么? 【发布时间】:2015-04-27 10:14:12 【问题描述】:

我目前正在尝试读取大量存储在名为 total 的数据表中的 excel 文件,然后我需要将其保存到 access 数据库中,它现在可以正常工作,但恐怕会由于需要读取的 excel 文件数量增加,效率非常低。

我找到了这个article 并将其用作我写作功能的基础。

        private void writeAccdb()
    
        if (File.Exists(saveFileDialog1.FileName))
            File.Delete(saveFileDialog1.FileName);
        OleDbConnection conn;
        OleDbDataAdapter adapter;

        ADOX.Catalog cat = new ADOX.Catalog();
        try
        
            cat.Create("Provider=Microsoft.ACE.OLEDB." + verFound + ".0;Data Source=" + saveFileDialog1.FileName);
        
        catch
        
            return;
        
        cat = null;
        try
        
            conn = new OleDbConnection("Provider=Microsoft.ACE.OLEDB." + verFound + ".0;Data Source=" + saveFileDialog1.FileName);
            conn.Open();
        
        catch
        
            return;
        
        try
        
            using (OleDbCommand cmd = new OleDbCommand("CREATE TABLE [Table_1] ([accdb_id] COUNTER PRIMARY KEY, [VALUE] DOUBLE, [TEXT] MEMO);", conn))
            
                cmd.ExecuteNonQuery();
            
        
        catch (Exception ex)  if (ex != null) ex = null;
        

        adapter = new OleDbDataAdapter("SELECT * FROM [Table_1]", conn);
        OleDbCommandBuilder cb = new OleDbCommandBuilder(adapter);
        DataTable dtMain = new DataTable();
        adapter.Fill(dtMain);



        //Slow process
        foreach (DataRow row in total.Rows)
        
            dtMain.Rows.Add(row.ItemArray);
        
        //Slow process



        adapter.Update(dtMain);
        conn.Close();
    

我尝试过使用 .Merge() 和 importrow 但我总是得到一个 180kb 的文件,它只包含列名和它们所持有的类型,但是当我检查 dtmain 时,它确实保存了我从总计中获得的变量,但是当我 itemarray 它工作正常。

虽然我已经在询问这个问题,但当创建文件时,它说程序仍在使用它,直到我关闭程序,但据我所知,与文件交互的所有内容都已关闭,我尝试对所有变量使用 dispose 但它仍然存在,这可能是什么问题?

编辑

所以我的主要问题是为什么 dtMain 在与 total 合并时不起作用,但是当单独添加每一行时它会起作用?

编辑 2

用户选择一个目录,他们要从中导入所有的 excel 文件

total 被设置为一个新的数据表并且所有的列都被填充了。

在目录中找到的所有excel文件的迭代被读取使用

        private OleDbConnection getExcelFile(string file)
    
        OleDbConnection conn;
        if (verFound != "")
            return new OleDbConnection("Provider=Microsoft.ACE.OLEDB." + verFound + ".0;Data Source=" + file + ";Extended Properties='Excel " + verFound + ".0 XML;HDR=YES;';");
        foreach(string v in versions)
            try
                conn = new OleDbConnection("Provider=Microsoft.ACE.OLEDB." + v + ".0;Data Source=" + file + ";Extended Properties='Excel " + v + ".0 XML;HDR=YES;';");
                conn.Open();
                conn.Close();
                verFound = v;
                return conn;
             catch 
                log("Version " + v + " är ej korrekt.");
            
        
        return null;
    

然后我尝试将excel文件数据与total合并,但如果结构不正确,则会被忽略。

所有文件合并后,datagridview 将作为数据源总计。

现在用户可以选择根据特定条件删除行。

最后是保存过程,所以总的来说它只是一个带有排除行选项的直接导入。

任何帮助将不胜感激。

【问题讨论】:

获得好答案的最佳方法是尝试一次只问一个非常具体的问题。我不确定这里的实际问题是什么。这不仅仅是一般的求助请求。 请edit 澄清您的问题: (1) 在尝试将数据插入 Access 之前,您是否将多个 Excel 文件的内容合并到 total DataTable 中? (2) 您是在修改 Excel 数据还是在total 中填充额外的列,还是直接从 Excel 导入? 您是否使用 OleDbDataAdapter 到 .fill 包含每个 Excel 文件中的数据的 DataTable,然后使用 .Merge 将该数据推送到 total DataTable 中? 完全正确。 OleDbDataAdapter sda = new OleDbDataAdapter(oconn); DataTable data = new DataTable(); sda.Fill(data); try total.Merge(data); catch corruptFiles = corruptFiles + file + "\r\n"; log(file + " verkar inte följa normen, ignoreras."); 【参考方案1】:

所以我的主要问题是为什么 dtMain 在与 total 合并时不起作用,但是当单独添加每一行时它会起作用?

原因是因为

    当现有 DataRow 被复制或合并到另一个 DataTable 中时,DataRow 的RowState 保持不变,并且 当我们使用 OleDbDataAdapter 的 .fill 方法填充 DataTable 时,所有行都使用“未更改”的 RowState 创建

因此,当您从 Excel 填充上游数据表时,这些行将作为“未更改”插入,而当这些行最终合并到“总”数据表中时,它们仍然是“未更改”。

示例代码:

string excelFileSpec = @"C:\Users\Gord\Desktop\Book1.xlsx";
string excelConnStr =
        "Provider=Microsoft.ACE.OLEDB.12.0;" +
        "Data Source=" + excelFileSpec + ";" +
        "Extended Properties=\"Excel 12.0 Xml;HDR=YES\";";
using (var excelCon = new OleDbConnection(excelConnStr))

    using (var excelDA = new OleDbDataAdapter("SELECT * FROM [Sheet1$]", excelCon))
    
        var total = new DataTable();
        excelDA.Fill(total);
        Console.WriteLine("DataAdapter.fill() put 0 row(s) into \"total\":", total.Rows.Count);
        int i = 0;
        foreach (DataRow r in total.Rows)
        
            Console.WriteLine("    total row[0]: RowState is \"1\"", i++, r.RowState);
        
        DataTable dtMain = total.Clone();
        dtMain.Merge(total);
        Console.WriteLine("dtMain.Merge(total); completed. \"dtMain\" contains 0 row(s):", dtMain.Rows.Count);
        i = 0;
        foreach (DataRow r in dtMain.Rows)
        
            Console.WriteLine("    dtMain row[0]: RowState is \"1\"", i++, r.RowState);
        
    

结果:

DataAdapter.fill() put 1 row(s) into "total":
    total row[0]: RowState is "Unchanged"
dtMain.Merge(total); completed. "dtMain" contains 1 row(s):
    dtMain row[0]: RowState is "Unchanged"

因此,当您的其他 DataAdapter 转到 .Update Access 数据库时,它会看到“dtMain”中的所有行都是“未更改”的,并且给人的印象是无事可做。

另一方面,当您将.Add 每一行添加到“dtMain”时,它们将作为“已添加”插入到 DataTable 中,因此当 .Update 发生时,它实际上确实会将“已添加”行发送到 Access 数据库。

【讨论】:

啊,你是对的,有点奇怪,他们从来没有设置为添加,因为它们实际上是添加的。非常感谢!

以上是关于合并的数据行不会在数据库中更新,但添加的数据行会。为啥?的主要内容,如果未能解决你的问题,请参考以下文章

如何合并 MySQL 表中的重复行

使用 SQL 数据适配器更新和插入行不会更新(仅插入)

SSIS 合并声明日期时间未更新

/var/lib/postgresql/data 尽管有明确的插入和更新行,但 docker 中时间刻度的盲挂载文件夹数据不会更新

C#中DataTable动态添加行和删除行的问题?

winform批量更新数据_长时间的执行会导致界面卡死