gpt4 book ai didi

c# - 更新 MySQL 会返回受影响的行,但实际上不会更新数据库

转载 作者:搜寻专家 更新时间:2023-10-30 23:38:10 24 4
gpt4 key购买 nike

我目前在带有 MonoDevelop 的 Ubuntu 上使用 Mono,使用与数据库中的表匹配的 DataTable 运行,并且应该尝试更新它。

以下代码使用从 XML 文件加载的数据集,该文件是从另一台机器上的 Dataset.WriteXML 创建的。

try
{
if(ds.Tables.Contains(s))
{
ds.Tables[s].AcceptChanges();
foreach(DataRow dr in ds.Tables[s].Rows)
dr.SetModified(); // Setting to modified so that it updates, rather than inserts, into the database
hc.Data.Database.Update(hc.Data.DataDictionary.GetTableInfo(s), ds.Tables[s]);
}
}
catch (Exception ex)
{
Log.WriteError(ex);
}

这是插入/更新数据库的代码。

public override int SQLUpdate(DataTable dt, string tableName)
{
MySqlDataAdapter da = new MySqlDataAdapter();
try
{
int rowsChanged = 0;
int tStart = Environment.TickCount;

da.SelectCommand = new MySqlCommand("SELECT * FROM " + tableName);
da.SelectCommand.Connection = connection;

MySqlCommandBuilder cb = new MySqlCommandBuilder(da);
da.UpdateCommand = cb.GetUpdateCommand();
da.DeleteCommand = cb.GetDeleteCommand();
da.InsertCommand = cb.GetInsertCommand();
da.ContinueUpdateOnError = true;
da.AcceptChangesDuringUpdate = true;

rowsChanged = da.Update(dt);

Log.WriteVerbose("Tbl={0},Rows={1},tics={2},", dt.TableName, rowsChanged, Misc.Elapsed(tStart));
return rowsChanged;
catch (Exception ex)
{
Log.WriteError("{0}", ex.Message);
return -1
}

我正在尝试上面的代码,rowsChanged 变为 4183,即我正在编辑的行数。然而,当我使用 HeidiSQL 检查数据库本身时,它根本没有改变任何东西。

我是否遗漏了一个步骤?

编辑:或者,能够覆盖数据库中的所有行也可以。这是一个使用 U 盘更新远程计算机的设置,强制它匹配源数据表。

编辑 2:添加了更多代码示例以显示 DT 的来源。 DataTable 在调用函数中预填充,所有行都有 DataRow.SetModified();应用。

编辑 3:附加信息。该表正在填充来自 XML 文件的数据。尝试在评论中建议修复。

编辑 4:添加调用代码,以防万一。

感谢您的帮助。

最佳答案

您可能想要研究的最简单方法可能是截断目标表,然后简单地将 XML 导入保存到它(关闭 AI,以便在必要时使用导入的 ID)。唯一的问题可能在于这样做的权利。否则……

您尝试执行的操作几乎可以使用Merge 方法处理。但是,它不能/不会知道已删除的行。由于该方法作用于DataTables,如果在 master 数据库中删除了一行,它只会不存在于 XML 提取中(相对于 DeletedRowState)。这些可以用循环清除。

同样,任何新行都可能获得不同的 AI int PK。为防止这种情况,只需在目标数据库中使用一个简单的非 AI PK,以便它可以接受任何数字。

XML 加载:

private DataTable LoadXMLToDT(string filename)
{
DataTable dt = new DataTable();
dt.ReadXml(filename);
return dt;
}

合并代码:

DataTable dtMaster = LoadXMLToDT(@"C:\Temp\dtsample.xml");
// just a debug monitor
var changes = dtMaster.GetChanges();

string SQL = "SELECT * FROM Destination";
using (MySqlConnection dbCon = new MySqlConnection(MySQLOtherDB))
{
dtSample = new DataTable();
daSample = new MySqlDataAdapter(SQL, dbCon);

MySqlCommandBuilder cb = new MySqlCommandBuilder(daSample);
daSample.UpdateCommand = cb.GetUpdateCommand();
daSample.DeleteCommand = cb.GetDeleteCommand();
daSample.InsertCommand = cb.GetInsertCommand();
daSample.FillSchema(dtSample, SchemaType.Source);
dbCon.Open();

// the destination table
daSample.Fill(dtSample);

// handle deleted rows
var drExisting = dtMaster.AsEnumerable()
.Select(x => x.Field<int>("Id"));
var drMasterDeleted = dtSample.AsEnumerable()
.Where( q => !drExisting.Contains(q.Field<int>("Id")));

// delete based on missing ID
foreach (DataRow dr in drMasterDeleted)
dr.Delete();

// merge the XML into the tbl read
dtSample.Merge(dtMaster,false, MissingSchemaAction.Add);

int rowsChanged = daSample.Update(dtSample);
}

无论出于何种原因,rowsChanged 总是报告与总行数一样多的更改。但是来自 Master/XML DataTable 的更改确实会流向其他/目标表。

删除代码获取现有 ID 的列表,然后根据新 XML 表是否包含具有该 ID 的行来确定需要从目标 DataTable 中删除哪些行。删除所有缺失的行,然后合并表。

关键是 dtSample.Merge(dtMaster,false, MissingSchemaAction.Add);,它将来自 dtMaster 的数据与 dtSample 合并。 false 参数允许传入的 XML 更改覆盖其他表中的值(并最终保存到数据库)。


我不知道某些问题(例如不匹配的 AI PK)是否是个大问题,但这似乎可以解决我能找到的所有问题。实际上,您要做的是 Database Synchronization .尽管只有一个表,只有几行,但上面的方法应该可行。

关于c# - 更新 MySQL 会返回受影响的行,但实际上不会更新数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38773418/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com