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.