2011-04-11 15 views
1

2 개의 DataTable을 비교하고 싶습니다. 내가 알아야 할 것은 내용 다른 예 또는 아니오입니다. 어느 누구도 그들을 비교할 수있는 빠른 방법을 추천 할 수 있습니까? 내용 (데이터) diffrent 경우in C# 데이터 테이블을 비교하고 싶습니다.

내가 알고 싶습니다

내가 object.Equals을 무시 확장 메서드를 작성합니다
+1

무엇을 비교 하시겠습니까? DB 구조? 또는 DB 구조 및 데이터입니까? –

+0

동일한 열 이름, 열 데이터 형식 및 동일한 행 순서를 가진 경우에만 두 테이블이 동일한 것으로 간주됩니까? – Greg

+0

무엇이 테이블을 비교할 수 없습니까? –

답변

3

는 테이블이 동일한 구조 (열 이름과 데이터 유형)

static bool AreTablesEqual(DataTable t1, DataTable t2) 
{ 
    // If the number of rows is different, no need to compare the data 
    if (t1.Rows.Count != t2.Rows.Count) 
     return false; 

    for (int i = 0; i < t1.Rows.Count; i++) 
    { 
     foreach(DataColumn col in t1.Columns) 
     { 
      if (!Equals(t1.Rows[i][col.ColumnName], t2.Rows[i][col.ColumnName])) 
       return false; 
     } 
    } 
    return true; 
} 
+1

두 테이블의 동등성은 두 테이블간에 일치하는 행의 순서에 따라 달라서는 안됩니다. (이것은 OP에서 받아 들여질 수도 있지만, 더 이상의 정보없이 말할 수는 없습니다.) 어떤 경우에도, 당신의 메소드를 호출하기 전에 테이블을 유일하게 정렬 할 필요가 있으며, 그 문제는 해결됩니다. –

+0

동일한 구조에 대한 가정이 필요하지 않습니다. 대답 http://stackoverflow.com/a/7518099/52277 또한 열을 비교합니다. –

+0

두 가지 질문 : ... 3, C#이 업데이트되었거나 잘못된 라이브러리를 사용하고 있습니까? ? 1) col.Name을 사용할 때 사실 col.ColumnName이 입니다. 2) t1 [i]를 사용하려고하면 "[]을 (를) 사용하여 인덱싱을 'System.Data'형식의 식에 적용 할 수 없습니다.DataTable ' – Machtyn

-1

두 개의 DataTable에의 소요하고 당신이 원하는 기준을 비교합니다.

+0

인터페이스 또는 클래스 메서드와 동일한 이름/서명을 사용하는 확장 메서드는 절대로 호출되지 않습니다 (http://msdn.microsoft.com/en-us/kr/을 참조하십시오). /library/bb383977.aspx, 컴파일시 _Binding 확장 메서드 _ 섹션) – beluchin

0

나는

bool AreEqual(DataTable d1, DataTable d2) 
    { 
     if (d1.Rows.Count != d2.Rows.Count) 
      return false; 
     for (int i = 0; i < d1.Rows.Count; i++) 
     { 
      var d1Row = d1.Rows[i]; 
      var d2Row = d2.Rows[i]; 
      for (int j = 0; j < d1Row.ItemArray.Count(); j++) 
      { 
       if (!d1Row[j].Equals(d2Row[j])) 
        return false; 
      } 
     } 

     return true; 
    } 
4

나는 내가 최근에 수행하고 발견 한 코드로이 문제를 가지고 생각을 가지고 가정 사용했다 내가하고 있었던 일은 실제로 작동하지 않았다. 그래서 저는 이것을 다시 고쳐야하고 최근에이 게시물을 보았습니다.

내가 이전에했던 일은 memorystreams와 두 문자열 모두에서 WriteXml을 사용하여 차이점을 찾는 한 번에 256 자씩 실행하는 것이 었습니다. 그 시간의 좋은 부분을 작동하는 동안, 나는 행과 열이 동일한 절차에서 호출 되었음에도 불구하고 다른 것과 동일한 순서로 반드시 필요하다는 것을 깨닫기 시작했습니다.

그래서 각 행의 해시 코드를 비교하여 수정했습니다. 이것은 결국 열과 행이 다른 순서 임에도 불구하고 모든 내용을 비교할 수있었습니다.

먼저 행 및 열 수와 같은 차이점에 대한 빠른 테스트를 수행 한 다음 첫 번째 테이블의 열이 두 번째 테이블에 있는지 확인합니다. 우리가 그렇게까지했다면, 해시 코드가있는 광범위한 테스트가 필요합니다. 나는 달리는 데 오랜 시간이 걸릴 것이라고 생각했지만 생각만큼 나쁘지는 않았다.

코드가 Visual Basic에 있다는 것을 알고 있습니다. C#을 찾고있는 것을 보았을 때 미안하지만, 전환하기가 쉽습니다.

이 스레드는 오래되었지만이 코드가 동일한 작업을 수행하는 데 도움이되기를 바랍니다. 셀 단위로 셀을 확인하는 것이 좋습니다.

''' <summary> 
''' Compares the data between both datatables to check if they have the same content or not. 
''' Columns and Rows do not need to be in the same order as the other, just that the data in any of them need to be the same. 
''' </summary> 
''' <param name="dtbl_a">The first datatable to compare.</param> 
''' <param name="dtbl_b">The second datatable to compare.</param> 
''' <param name="debug">For troubleshooting and checking the function is working correctly. Typically this is 'false'.</param> 
''' <returns>Boolean: False if the data between the two datatables are different, True if the data between them are the same.</returns> 
''' <remarks></remarks> 
Public Function dataTablesAreEqual _ 
            (ByRef dtbl_a As System.Data.DataTable, _ 
            ByRef dtbl_b As System.Data.DataTable, _ 
            ByVal debug As System.Boolean) As System.Boolean 

    Dim recordCount(1) As System.Int32 
    Dim columnCount(1) As System.Int32 
    Dim length(1) As System.Int32 
    Dim dtbl_check(1) As System.Data.DataTable 
    Dim debugMessage As New System.Text.StringBuilder 
    Dim errorMessage As System.String 
    Dim result As System.Boolean 

    Try 
     If debug = True Then 
      debugMessage.AppendLine("checking: priliminary (and easy to see) tests being done...") 
      debugMessage.AppendLine("checking: what is nothing and what is not nothing.") 

     End If 

     If dtbl_a Is Nothing And dtbl_b Is Nothing Then 
      result = True 

      If debug = True Then 
       debugMessage.AppendLine("decision: " & result.ToString & "!") 
       debugMessage.AppendLine(" reason: dtbl_a Is Nothing And dtbl_b Is Nothing.") 

      End If 

      Return result 

     ElseIf dtbl_a Is Nothing And dtbl_b IsNot Nothing Then 
      result = False 

      If debug = True Then 
       debugMessage.AppendLine("decision: " & result.ToString & "!") 
       debugMessage.AppendLine(" reason: dtbl_a Is Nothing And dtbl_b IsNot Nothing.") 

      End If 

      Return result 

     ElseIf dtbl_a IsNot Nothing And dtbl_b Is Nothing Then 
      result = False 

      If debug = True Then 
       debugMessage.AppendLine("decision: " & result.ToString & "!") 
       debugMessage.AppendLine(" reason: dtbl_a IsNot Nothing And dtbl_b Is Nothing.") 

      End If 

      Return result 

     End If 

     If debug = True Then 
      debugMessage.AppendLine("checking: differences in row and column counts.") 

     End If 

     recordCount(0) = dtbl_a.Rows.Count 
     columnCount(0) = dtbl_a.Columns.Count 

     recordCount(1) = dtbl_b.Rows.Count 
     columnCount(1) = dtbl_b.Columns.Count 

     If recordCount(0) <> recordCount(1) Then 
      result = False 

      If debug = True Then 
       debugMessage.AppendLine("decision: " & result.ToString & "!") 
       debugMessage.AppendLine(" reason: the # of rows are different.") 
       debugMessage.AppendLine(" reason: dtbl_a has " & recordCount(0) & " record(s) and dtbl_b has " & recordCount(1) & " record(s).") 

      End If 

      Return result 

     ElseIf columnCount(0) <> columnCount(1) Then 
      result = False 

      If debug = True Then 
       debugMessage.AppendLine("decision: " & result.ToString & "!") 
       debugMessage.AppendLine(" reason: the # of columns are different.") 
       debugMessage.AppendLine(" reason: dtbl_a has " & columnCount(0) & " column(s) and dtbl_b has " & columnCount(1) & " column(s).") 

      End If 

      Return result 

     End If 

     Dim lowerBound_Records As System.Int32 
     Dim upperBound_Records As System.Int32 
     Dim current_Record As System.Int32 
     Dim lowerBound_Columns As System.Int32 
     Dim upperBound_Columns As System.Int32 
     Dim current_Column As System.Int32 

     lowerBound_Records = 0 
     upperBound_Records = (recordCount(0) - 1) 
     lowerBound_Columns = 0 
     upperBound_Columns = (columnCount(0) - 1) 

     If debug = True Then 
      debugMessage.AppendLine("checking: columns exist in both tables (can be in different order).") 

     End If 

     For current_Column = lowerBound_Columns To upperBound_Columns 
      Dim columnName As System.String 
      Dim exists As System.Boolean 

      columnName = dtbl_a.Columns(current_Column).ColumnName 
      exists = dtbl_b.Columns.Contains(columnName) 

      If exists = False Then 
       result = False 

       If debug = True Then 
        debugMessage.AppendLine("decision: " & result.ToString & "!") 
        debugMessage.AppendLine(" reason: the column [" & columnName & "] in dtbl_a does NOT EXIST in dtbl_b.") 

       End If 

       Return result 

      End If 

     Next current_Column 

     dtbl_check(0) = New System.Data.DataTable 
     dtbl_check(0).Columns.Add("index", GetType(System.Int32)) 
     dtbl_check(0).Columns.Add("hashCode", GetType(System.Int32)) 
     dtbl_check(0).Columns.Add("checked", GetType(System.DateTime)) 

     If debug = True Then 
      dtbl_check(0).Columns.Add("dataRow", GetType(System.String)) 

     End If 

     dtbl_check(0).PrimaryKey = New System.Data.DataColumn() {dtbl_check(0).Columns("index"), dtbl_check(0).Columns("hashCode")} 
     dtbl_check(1) = dtbl_check(0).Copy 

     If debug = True Then 
      debugMessage.AppendLine("checking: going for the extensive data content check (rows can be in different order).") 
      debugMessage.AppendLine("checking: getting hashcodes from dtbl_a started: " & System.DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss.ffff")) 

     End If 

     For current_Record = lowerBound_Records To upperBound_Records 
      Dim dataRow_check As New System.Text.StringBuilder 

      dataRow_check.Append("<dataRow>") 
      For current_Column = lowerBound_Columns To upperBound_Columns 
       Dim columnName As System.String 
       Dim valueIsNull As System.Boolean 
       Dim value As System.String 

       columnName = dtbl_a.Columns(current_Column).ColumnName 
       valueIsNull = System.Convert.IsDBNull(dtbl_a.Rows(current_Record).Item(columnName)) 

       If valueIsNull = False Then 
        value = dtbl_a.Rows(current_Record).Item(columnName).ToString 

       Else 
        value = "[null]" 

       End If 

       dataRow_check.Append("<" & columnName & ">" & value & "</" & columnName & ">") 

      Next current_Column 

      dataRow_check.Append("</dataRow>") 

      Dim newRow As System.Data.DataRow = dtbl_check(0).NewRow 
      Call newRow.BeginEdit() 
      newRow.Item("index") = current_Record 
      newRow.Item("hashCode") = dataRow_check.ToString.GetHashCode 
      newRow.Item("checked") = System.Convert.DBNull 

      If debug = True Then 
       newRow.Item("dataRow") = dataRow_check.ToString 

      End If 

      Call newRow.EndEdit() 
      Call dtbl_check(0).Rows.Add(newRow) 
      dataRow_check = Nothing 

     Next current_Record 

     If debug = True Then 
      debugMessage.AppendLine("checking: finished hashcodes for dtbl_a ended: " & System.DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss.ffff")) 
      debugMessage.AppendLine("checking: getting hashcodes from dtbl_b and cross checking using dtbl_a started: " & System.DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss.ffff")) 

     End If 

     For current_Record = lowerBound_Records To upperBound_Records 
      Dim dataRow_check As New System.Text.StringBuilder 
      Dim checked As System.DateTime 

      checked = System.DateTime.Now 
      dataRow_check.Append("<dataRow>") 

      For current_Column = lowerBound_Columns To upperBound_Columns 
       Dim columnName As System.String 
       Dim valueIsNull As System.Boolean 
       Dim value As System.String 

       columnName = dtbl_a.Columns(current_Column).ColumnName 

       Try 
        valueIsNull = System.Convert.IsDBNull(dtbl_b.Rows(current_Record).Item(columnName)) 

       Catch exc As System.Exception 
        result = False 
        Return result 

       End Try 

       If valueIsNull = False Then 
        value = dtbl_b.Rows(current_Record).Item(columnName).ToString 

       Else 
        value = "[null]" 

       End If 

       dataRow_check.Append("<" & columnName & ">" & value & "</" & columnName & ">") 

      Next current_Column 

      dataRow_check.Append("</dataRow>") 

      Dim selectQuery As System.String 
      Dim dataRows() As System.Data.DataRow 
      Dim hashCode As System.Int32 

      hashCode = dataRow_check.ToString.GetHashCode 
      selectQuery = "[hashCode] = " & hashCode.ToString & " and [checked] is null " 
      dataRows = dtbl_check(0).Select(selectQuery) 

      If dataRows.Length > 0 Then 
       Call dataRows(0).BeginEdit() 
       dataRows(0).Item("checked") = checked 
       Call dataRows(0).EndEdit() 

       Dim newRow As System.Data.DataRow = dtbl_check(1).NewRow 
       Call newRow.BeginEdit() 
       newRow.Item("index") = dataRows(0).Item("index") 
       newRow.Item("hashCode") = dataRows(0).Item("hashCode") 
       newRow.Item("checked") = checked 

       If debug = True Then 
        newRow.Item("dataRow") = dataRow_check.ToString 

       End If 

       Call newRow.EndEdit() 
       Call dtbl_check(1).Rows.Add(newRow) 

      Else 
       result = False 

       If debug = True Then 
        debugMessage.AppendLine("checking: finished hashcodes for dtbl_b ended: " & System.DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss.ffff")) 
        debugMessage.AppendLine("decision: " & result.ToString & "!") 
        debugMessage.AppendLine(" reason: a row in dtbl_b doesn't match up in dtbl_a (either due to changes or didn't exist).") 
        debugMessage.AppendLine(" dataRow: " & dataRow_check.ToString) 

       End If 

       dataRow_check = Nothing 

       Return result 

      End If 

      dataRows = Nothing 
      dataRow_check = Nothing 

     Next current_Record 

     result = True 

     If debug = True Then 
      debugMessage.AppendLine("checking: finished hashcodes for dtbl_b ended: " & System.DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss.ffff")) 
      debugMessage.AppendLine("decision: " & result.ToString & "!") 
      debugMessage.AppendLine(" reason: all " & recordCount(0) & " record(s) match up between both tables.") 

     End If 

    Catch exc_Exception As System.Exception 
     errorMessage = exc_Exception.Message 
     result = False 

     If debug = True Then 
      debugMessage.AppendLine("exception in dataTablesAreEqual!") 
      debugMessage.AppendLine("decision: " & result.ToString & "!") 
      debugMessage.AppendLine(" message: " & errorMessage) 

     End If 

    Finally 
     If dtbl_check(1) IsNot Nothing Then 
      Call dtbl_check(1).Clear() 
      dtbl_check(1) = Nothing 

     End If 

     If dtbl_check(0) IsNot Nothing Then 
      Call dtbl_check(0).Clear() 
      dtbl_check(0) = Nothing 

     End If 

     If debug = True Then 
      Call System.Diagnostics.Debug.WriteLine(debugMessage.ToString) 

     End If 

     debugMessage = Nothing 

    End Try 

    Return result 

End Function 
관련 문제