Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Das Aktualisieren von MySQL gibt betroffene Zeilen zurück, aktualisiert jedoch nicht die Datenbank

Der einfachste Weg, den Sie vielleicht untersuchen möchten, besteht darin, die Zieltabelle abzuschneiden und dann einfach den XML-Import darin zu speichern (mit deaktivierter AI, damit bei Bedarf die importierte ID verwendet wird). Das einzige Problem könnten die Rechte dafür sein. Sonst...

Was Sie versuchen, kann fast mit Merge gehandhabt werden Methode. Es kann/will jedoch nichts über gelöschte Zeilen. wissen Da die Methode auf DataTables wirkt , wenn eine Zeile in der Master-Datenbank gelöscht wurde, ist sie einfach nicht im XML-Extrakt vorhanden (im Gegensatz zu einem RowState von Deleted ). Diese können mit einer Schleife ausgesondert werden.

Ebenso können alle neuen Zeilen einen anderen PK für einen AI int erhalten. Um dies zu verhindern, verwenden Sie einfach einen einfachen Nicht-AI-PK in der Zieldatenbank, damit er jede Nummer akzeptieren kann.

Das XML-Laden:

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

Der Zusammenführungscode:

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);
}

Aus welchem ​​Grund auch immer, rowsChanged meldet immer so viele Änderungen, wie Zeilen insgesamt vorhanden sind. Aber Änderungen von der Master-/XML-Datentabelle fließen in die andere/Zieltabelle.

Der Löschcode ruft eine Liste vorhandener IDs ab und bestimmt dann, welche Zeilen aus der Ziel-DataTable gelöscht werden müssen, je nachdem, ob die neue XML-Tabelle eine Zeile mit dieser ID enthält oder nicht. Alle fehlenden Zeilen werden gelöscht, dann werden die Tabellen zusammengeführt.

Der Schlüssel ist dtSample.Merge(dtMaster,false, MissingSchemaAction.Add); der die Daten von dtMaster zusammenführt mit dtSample . Der false param ermöglicht es den eingehenden XML-Änderungen, Werte in der anderen Tabelle zu überschreiben (und schließlich in der Datenbank gespeichert zu werden).

Ich habe keine Ahnung, ob einige der Probleme wie nicht übereinstimmende KI-PKs eine große Sache sind oder nicht, aber dies scheint alles zu behandeln, was ich finden konnte. In Wirklichkeit versuchen Sie Datenbanksynchronisierung . Obwohl mit einer Tabelle und nur wenigen Zeilen das obige funktionieren sollte.