Mysql
 sql >> Database >  >> RDS >> Mysql

L'aggiornamento di MySQL restituisce le righe interessate, ma in realtà non aggiorna il database

Il modo più semplice che potresti voler esaminare potrebbe essere TRUNCATE la tabella di destinazione, quindi salvare semplicemente l'importazione XML su di essa (con AI disattivato in modo che utilizzi l'ID importato se necessario). L'unico problema potrebbe essere con i diritti per farlo. Altrimenti...

Quello che stai cercando di fare può quasi essere gestito utilizzando il Merge metodo. Tuttavia, non può/non conoscerà le righe eliminate. Poiché il metodo agisce su DataTables , se una riga è stata eliminata nel database principale, semplicemente non esisterà nell'estrazione XML (rispetto a RowState di Deleted ). Questi possono essere eliminati con un ciclo.

Allo stesso modo, qualsiasi nuova riga potrebbe ottenere un PK diverso per un int AI. Per evitarlo, usa un semplice PK non AI nel db di destinazione in modo che possa accettare qualsiasi numero.

Il caricamento XML:

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

Il codice di unione:

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

Per qualsiasi motivo, rowsChanged riporta sempre tante modifiche quante sono le righe totali. Ma le modifiche dalla tabella dati master/XML passano all'altra tabella/destinazione.

Il codice di eliminazione ottiene un elenco di ID esistenti, quindi determina quali righe devono essere eliminate dalla DataTable di destinazione in base al fatto che la nuova tabella XML abbia una riga con tale ID o meno. Tutte le righe mancanti vengono eliminate, quindi le tabelle vengono unite.

La chiave è dtSample.Merge(dtMaster,false, MissingSchemaAction.Add); che unisce i dati da dtMaster con dtSample . Il false param è ciò che consente alle modifiche XML in entrata di sovrascrivere i valori nell'altra tabella (ed eventualmente di essere salvate nel db).

Non ho idea se alcuni dei problemi come i PK AI non corrispondenti siano un grosso problema o meno, ma questo sembra gestire tutto ciò che sono riuscito a trovare. In realtà, quello che stai cercando di fare è Sincronizzazione del database . Sebbene con una tabella e solo poche righe, quanto sopra dovrebbe funzionare.