Det enklaste sättet som du kanske vill undersöka kan vara att TRUNCATE destinationstabellen och sedan helt enkelt spara XML-importen till den (med AI avstängd så att den använder det importerade ID:t om det behövs). Det enda problemet kan vara med rättigheterna att göra det. Annars...
Det du försöker göra kan nästan hanteras med Merge
metod. Däremot kan/vil den inte veta om borttagna rader. Eftersom metoden verkar på DataTables
, om en rad raderades i huvuddatabasen, kommer den helt enkelt inte att finnas i XML-extraktet (mot en RowState
av Deleted
). Dessa kan såras bort med en slinga.
På samma sätt kan alla nya rader få en annan PK för en AI-int. För att förhindra det, använd bara en enkel icke-AI PK i destinationsdatabasen så att den kan acceptera vilket nummer som helst.
XML-laddningen:
private DataTable LoadXMLToDT(string filename)
{
DataTable dt = new DataTable();
dt.ReadXml(filename);
return dt;
}
Sammanfogningskoden:
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);
}
Av någon anledning, rowsChanged
rapporterar alltid lika många ändringar som det finns totalt antal rader. Men ändringar från Master/XML DataTable går igenom till den andra/destinationstabellen.
Raderingskoden får en lista över befintliga ID:n och bestämmer sedan vilka rader som måste tas bort från destinationsdatatabellen genom att den nya XML-tabellen har en rad med det ID:t eller inte. Alla rader som saknas tas bort, sedan slås tabellerna samman.
Nyckeln är dtSample.Merge(dtMaster,false, MissingSchemaAction.Add);
som slår samman data från dtMaster
med dtSample
. false
param är det som gör att de inkommande XML-ändringarna kan skriva över värden i den andra tabellen (och så småningom sparas i db).
Jag har ingen aning om om några av problemen som icke-matchande AI PK är en stor sak eller inte, men det här verkar hantera allt jag kan hitta. I verkligheten är det du försöker göra Databassynkronisering . Även om med en tabell och bara några rader borde ovanstående fungera.