合并的数据行不会在数据库中更新,但添加的数据行会。为啥?
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 数据库。
【讨论】:
啊,你是对的,有点奇怪,他们从来没有设置为添加,因为它们实际上是添加的。非常感谢!以上是关于合并的数据行不会在数据库中更新,但添加的数据行会。为啥?的主要内容,如果未能解决你的问题,请参考以下文章
/var/lib/postgresql/data 尽管有明确的插入和更新行,但 docker 中时间刻度的盲挂载文件夹数据不会更新