2016-08-04 2 views
1

현재 데이터베이스의 테이블과 일치하는 DataTable을 사용하여 MonoDevelop와 함께 Mono를 우분투에서 사용하고 있으며이를 업데이트해야합니다.MySQL을 업데이트하면 영향을받는 행이 반환되지만 데이터베이스는 실제로 업데이트되지 않습니다.

다음 코드는 다른 컴퓨터의 Dataset.WriteXML에서 만든 XML 파일에서로드 된 데이터 집합을 사용합니다.

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가 꺼져 있으므로 필요한 경우 가져온 ID를 사용합니다). 유일한 문제는이를 수행 할 권리가있을 수 있습니다. 그렇지 않으면 ...

당신이 캔을 할 려 거의Merge 방법을 사용하여 처리 할 수. 그러나 삭제 된 행에 대해서는 을 알 수 없거나 알 수 없습니다.이 메서드는 DataTables에서 작동하기 때문에 마스터 데이터베이스에서 행이 삭제 된 경우 XML 추출 (RowStateDeleted)에 해당 행이 존재하지 않습니다. 이것들은 루프로 제거 될 수 있습니다.

마찬가지로 새 행은 AI int에 대해 다른 PK를 얻을 수 있습니다. 이를 막기 위해 대상 데이터베이스에서 단순한 비 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의 변경 사항은 다른/대상 테이블을 통해 흐릅니다.

삭제 코드는 기존 ID 목록을 가져 와서 새 XML 테이블에 해당 ID가있는 행이 있는지 여부에 따라 대상 DataTable에서 삭제해야하는 행을 결정합니다.누락 된 행이 모두 삭제 된 후 테이블이 병합됩니다.

키는 dtSample.Merge(dtMaster,false, MissingSchemaAction.Add);이며 dtMaster의 데이터와 dtSample의 데이터가 병합됩니다. false param은 들어오는 XML 변경 사항이 다른 테이블의 값을 덮어 쓰도록 허용하므로 결국 데이터베이스에 저장됩니다.


나는 비 매칭 AI PK와 같은 몇 가지 문제가 큰 문제인지 아닌지 모르겠지만,이게 내가 찾을 수있는 모든 것을 처리 할 것으로 보인다. 실제로, 당신이하려고하는 것은 Database Synchronization입니다. 하나의 테이블과 몇 개의 행만 있으면 위의 내용이 작동합니다.

+1

작은 편집을 한 후에 Fill, Merge가 트릭을했습니다! Deleted Rows에 대해서도 감사드립니다. 조금 다르게 처리하겠습니다. 당신이 오기 전에 이것으로 8 시간 동안 머리를 긁어 냈습니다! – user3169698

관련 문제