Den enkleste måde, du måske ønsker at se nærmere på, kan være at TRUNCATE destinationstabellen og derefter blot gemme XML-importen til den (med AI slået fra, så den bruger det importerede ID, hvis det er nødvendigt). Det eneste problem kan være med rettighederne til at gøre det. Ellers...
Det, du forsøger at gøre, kan næsten håndteres ved hjælp af Merge
metode. Den kan/vil dog ikke vide om slettede rækker. Da metoden virker på DataTables
, hvis en række blev slettet i masterdatabasen, vil den simpelthen ikke eksistere i XML-uddraget (versus en RowState
af Deleted
). Disse kan luges ud med en løkke.
Ligeledes kan alle nye rækker få en anden PK for en AI int. For at forhindre det skal du blot bruge en simpel ikke-AI PK i destinationsdatabasen, så den kan acceptere et hvilket som helst nummer.
XML-indlæsningen:
private DataTable LoadXMLToDT(string filename)
{
DataTable dt = new DataTable();
dt.ReadXml(filename);
return dt;
}
Fletningskoden:
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);
}
Uanset årsagen, rowsChanged
rapporterer altid lige så mange ændringer, som der er samlede rækker. Men ændringer fra Master/XML-datatabellen går igennem til den anden/destinationstabel.
Slettekoden får en liste over eksisterende id'er og bestemmer derefter, hvilke rækker der skal slettes fra destinationsdatatabellen ved, om den nye XML-tabel har en række med dette id eller ej. Alle de manglende rækker slettes, hvorefter tabellerne slås sammen.
Nøglen er dtSample.Merge(dtMaster,false, MissingSchemaAction.Add);
som fletter dataene fra dtMaster
med dtSample
. false
param er det, der tillader de indkommende XML-ændringer at overskrive værdier i den anden tabel (og til sidst gemmes i db).
Jeg aner ikke, om nogle af problemerne som ikke-matchende AI PK'er er en big deal eller ej, men dette ser ud til at håndtere alt, hvad jeg kunne finde. I virkeligheden er det, du forsøger at gøre, Databasesynkronisering . Selvom med én tabel og kun et par rækker, burde ovenstående fungere.