Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

A atualização do MySQL retorna as linhas afetadas, mas não atualiza o banco de dados


A maneira mais simples que você pode querer examinar pode ser TRUNCATE a tabela de destino e, em seguida, basta salvar a importação XML para ela (com o AI desativado para que ele use o ID importado, se necessário). O único problema pode ser com os direitos de fazer isso. Por outro lado...

O que você está tentando fazer pode quase ser tratado usando o Merge método. No entanto, ele não pode/não saberá sobre linhas excluídas. Como o método está atuando em DataTables , se uma linha foi excluída no banco de dados mestre, ela simplesmente não existirá na extração XML (versus um RowState de Deleted ). Estes podem ser eliminados com um loop.

Da mesma forma, quaisquer novas linhas podem obter um PK diferente para um int AI. Para evitar isso, basta usar um simples PK não AI no banco de dados de destino para que ele possa aceitar qualquer número.

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

O código de mesclagem:
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);
}

Por qualquer motivo, rowsChanged sempre relata tantas alterações quanto o total de linhas. Mas as alterações do Master/XML DataTable fluem para a outra tabela/destino.

O código de exclusão obtém uma lista de IDs existentes e determina quais linhas precisam ser excluídas do DataTable de destino, independentemente de a nova tabela XML ter uma linha com esse ID ou não. Todas as linhas ausentes são excluídas e as tabelas são mescladas.

A chave é dtSample.Merge(dtMaster,false, MissingSchemaAction.Add); que mescla os dados de dtMaster com dtSample . O false param é o que permite que as alterações XML de entrada sobrescrevam valores na outra tabela (e eventualmente sejam salvas no banco de dados).

Não tenho ideia se alguns dos problemas, como PKs de IA não correspondentes, são um grande problema ou não, mas isso parece lidar com tudo o que pude encontrar. Na realidade, o que você está tentando fazer é Sincronização de banco de dados . Embora com uma tabela e apenas algumas linhas, o acima deve funcionar.