2016-08-04 6 views
1

Я в настоящее время использую Mono на Ubuntu с MonoDevelop, работая с DataTable, сопоставляя таблицу в базе данных и пытаюсь ее обновить.Обновление MySQL возвращает затронутые строки, но фактически не обновляет базу данных

В следующем коде используется набор данных, загруженный из файла XML, который был создан из Dataset.WriteXML на другом компьютере.

try 
{ 
    if(ds.Tables.Contains(s)) 
    {       
     ds.Tables[s].AcceptChanges(); 
     foreach(DataRow dr in ds.Tables[s].Rows) 
      dr.SetModified(); // Setting to modified so that it updates, rather than inserts, into the database 
     hc.Data.Database.Update(hc.Data.DataDictionary.GetTableInfo(s), ds.Tables[s]); 
    } 
      } 
      catch (Exception ex) 
      { 
       Log.WriteError(ex); 
      } 

Это код для вставки/обновления в базе данных.

public override int SQLUpdate(DataTable dt, string tableName) 
    { 
     MySqlDataAdapter da = new MySqlDataAdapter(); 
     try 
     { 
      int rowsChanged = 0; 
      int tStart = Environment.TickCount; 

      da.SelectCommand = new MySqlCommand("SELECT * FROM " + tableName); 
      da.SelectCommand.Connection = connection; 

      MySqlCommandBuilder cb = new MySqlCommandBuilder(da); 
      da.UpdateCommand = cb.GetUpdateCommand(); 
      da.DeleteCommand = cb.GetDeleteCommand(); 
      da.InsertCommand = cb.GetInsertCommand(); 
      da.ContinueUpdateOnError = true; 
      da.AcceptChangesDuringUpdate = true; 

      rowsChanged = da.Update(dt); 

      Log.WriteVerbose("Tbl={0},Rows={1},tics={2},", dt.TableName, rowsChanged, Misc.Elapsed(tStart)); 
      return rowsChanged; 
      catch (Exception ex) 
      { 
       Log.WriteError("{0}", ex.Message); 
       return -1 
      } 

Я пытаюсь выполнить вышеуказанный код, а rowsChanged становится 4183, количество строк, которые я редактирую. Однако, когда я использую HeidiSQL для проверки самой базы данных, она ничего не меняет.

Есть ли какой-то шаг, который мне не хватает?

Редактировать: Альтернативно, возможность перезаписывать все строки в базе данных также будет работать. Это настройка для обновления удаленных компьютеров с помощью USB-накопителей, что вынуждает их сопоставлять таблицу исходных данных.

Редактировать 2: Добавлен дополнительный образец кода, чтобы показать источник DT. DataTable предварительно заполняется в вызывающей функции, и все строки имеют DataRow.SetModified(); применяется.

Редактировать 3: Дополнительная информация. Таблица заполняется данными из файла XML. Попытка исправить в комментариях.

Редактирование 4: добавление кода вызова на всякий случай.

Благодарим за помощь.

+0

Серверы/соединения MySQL обычно имеют параметр для того, следует ли возвращать затронутые строки или сопоставляемые строки; может быть, что эффективная настройка для этих двух сред различна. – Uueerdo

+1

что в DT? Он заполнен в другом месте? Он просто выходит из ниоткуда в этом коде. – Plutonix

+0

Добавлена ​​запрашиваемая информация. – user3169698

ответ

1

Самый простой способ, которым вы можете захотеть заглянуть, может состоять в том, чтобы TRUNCATE в таблице назначения, а затем просто сохраните им импорт XML (при выключенном AI, чтобы при необходимости использовать импортированный идентификатор). Единственная проблема может заключаться в правах на это. В противном случае ...

То, что вы пытаетесь сделать, можете почти быть обработаны с использованием метода Merge. Однако он не может/не знает о удаленных строках. Поскольку метод действует на DataTables, если строка была удалена в основной базе данных, она просто не будет существовать в извлечении XML (по сравнению с RowState из Deleted). Они могут быть отсечены с помощью петли.

Аналогично, любые новые строки могут иметь различный PK для AI int. Чтобы этого избежать, просто используйте простой не-AI PK в db назначения, чтобы он мог принимать любое число.

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 - это то, что позволяет входящим изменениям XML переписывать значения в другой таблице (и, в конечном итоге, сохраняется в db).


Я понятия не имею, некоторые из таких вопросов, как не соответствия AI ПКС ли большое дело или нет, но это, кажется, обрабатывать все, что я мог бы найти. На самом деле то, что вы пытаетесь сделать, это Database Synchronization. Хотя с одной таблицей и несколькими строками выше должно работать.

+1

После небольшого редактирования Fill Then Merge сделал трюк! Я также благодарю вас за предмет «Удаленные строки», хотя мы справляемся с этим несколько иначе. Это заняло у меня 8 часов царапин на голове, прежде чем вы пришли! – user3169698

 Смежные вопросы

  • Нет связанных вопросов^_^