Най-простият начин, който може да искате да разгледате, може да бъде да ОТРЕЖЕТЕ целевата таблица, след което просто да запишете импортирания XML в нея (с изключен AI, така че да използва импортирания идентификатор, ако е необходимо). Единственият проблем може да е с правата за това. В противен случай...
Това, което се опитвате да направите, можепочти се обработва с помощта на Merge
метод. Той обаче не може/не иска да знае за изтрити редове. Тъй като методът действа върху DataTables
, ако ред е бил изтрит в основната база данни, той просто няма да съществува в XML извлечението (срещу RowState
от Deleted
). Те могат да бъдат премахнати с примка.
По същия начин всички нови редове може да получат различен PK за AI int. За да предотвратите това, просто използвайте прост не-AI PK в целевата база данни, така че да може да приема произволен номер.
Зареждането на XML:
private DataTable LoadXMLToDT(string filename)
{
DataTable dt = new DataTable();
dt.ReadXml(filename);
return dt;
}
Кодът за сливане:
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);
}
По някаква причина, rowsChanged
винаги отчита толкова промени, колкото има общо редове. Но промените от Master/XML DataTable преминават към другата/целевата таблица.
Кодът за изтриване получава списък със съществуващи идентификатори, след което определя кои редове трябва да бъдат изтрити от целевата DataTable според това дали новата XML таблица има ред с този идентификатор или не. Всички липсващи редове се изтриват, след което таблиците се обединяват.
Ключът е dtSample.Merge(dtMaster,false, MissingSchemaAction.Add);
който обединява данните от dtMaster
с dtSample
. false
param е това, което позволява на входящите XML промени да презаписват стойности в другата таблица (и в крайна сметка да бъдат записани в db).
Нямам представа дали някои от проблемите, като несъответстващи AI PK, са голяма работа или не, но това изглежда се справя с всичко, което успях да намеря. В действителност това, което се опитвате да направите, е Синхронизиране на база данни . Въпреки че с една таблица и само няколко реда, горното трябва да работи.