2016-08-04 79 views
1

我目前在使用MonoDevelop的Ubuntu上使用Mono,使用与数据库中的表匹配的DataTable运行,并且应该尝试更新它。正在更新MySQL返回受影响的行,但实际上并未更新数据库

以下代码使用从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来检查数据库本身时,它根本不会改变任何内容。

有没有我失踪的一步?

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

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

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

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

谢谢你的帮助。

+0

MySQL服务器/连接通常会设置是否返回受影响的行或匹配的行;这可能是这两种环境的有效设置不同。 – Uueerdo

+1

DT是什么?它在别处填满了吗?它只是在代码中出现。 – Plutonix

+0

添加了所需的信息。 – user3169698

回答

1

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

什么你正在尝试做的CAN 几乎使用Merge方法来处理。但是,它不能/不会知道关于删除的行。由于该方法在DataTables上执行,因此如果在master数据库中删除了一行,它将不会存在于XML抽取中(而RowState的是Deleted)。这些可以循环清除。

同样,对于一个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因为总共有行始终报告发生了许多变化。但是来自主/ XML数据表的更改会流向其他/目标表。

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

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


我不知道有些像非匹配AI的PK问题是一个大问题或没有,但这似乎处理所有我能找到。实际上,你要做的是Database Synchronization。虽然有一张桌子,只有几行,但上述内容应该可以工作。

+1

经过一些小小的编辑,Fill然后合并做了诡计!我也感谢你的删除行的事情,尽管我们处理这个有点不同。在你来之前,这花了我8个小时的头部划伤! – user3169698

相关问题