2 개의 DataTable을 비교하고 싶습니다. 내가 알아야 할 것은 내용 다른 예 또는 아니오입니다. 어느 누구도 그들을 비교할 수있는 빠른 방법을 추천 할 수 있습니까? 내용 (데이터) diffrent 경우in C# 데이터 테이블을 비교하고 싶습니다.
내가 알고 싶습니다
내가 object.Equals을 무시 확장 메서드를 작성합니다2 개의 DataTable을 비교하고 싶습니다. 내가 알아야 할 것은 내용 다른 예 또는 아니오입니다. 어느 누구도 그들을 비교할 수있는 빠른 방법을 추천 할 수 있습니까? 내용 (데이터) diffrent 경우in C# 데이터 테이블을 비교하고 싶습니다.
내가 알고 싶습니다
내가 object.Equals을 무시 확장 메서드를 작성합니다는 테이블이 동일한 구조 (열 이름과 데이터 유형)
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;
}
두 테이블의 동등성은 두 테이블간에 일치하는 행의 순서에 따라 달라서는 안됩니다. (이것은 OP에서 받아 들여질 수도 있지만, 더 이상의 정보없이 말할 수는 없습니다.) 어떤 경우에도, 당신의 메소드를 호출하기 전에 테이블을 유일하게 정렬 할 필요가 있으며, 그 문제는 해결됩니다. –
동일한 구조에 대한 가정이 필요하지 않습니다. 대답 http://stackoverflow.com/a/7518099/52277 또한 열을 비교합니다. –
두 가지 질문 : ... 3, C#이 업데이트되었거나 잘못된 라이브러리를 사용하고 있습니까? ? 1) col.Name을 사용할 때 사실 col.ColumnName이 입니다. 2) t1 [i]를 사용하려고하면 "[]을 (를) 사용하여 인덱싱을 'System.Data'형식의 식에 적용 할 수 없습니다.DataTable ' – Machtyn
두 개의 DataTable에의 소요하고 당신이 원하는 기준을 비교합니다.
인터페이스 또는 클래스 메서드와 동일한 이름/서명을 사용하는 확장 메서드는 절대로 호출되지 않습니다 (http://msdn.microsoft.com/en-us/kr/을 참조하십시오). /library/bb383977.aspx, 컴파일시 _Binding 확장 메서드 _ 섹션) – beluchin
나는
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;
}
나는 내가 최근에 수행하고 발견 한 코드로이 문제를 가지고 생각을 가지고 가정 사용했다 내가하고 있었던 일은 실제로 작동하지 않았다. 그래서 저는 이것을 다시 고쳐야하고 최근에이 게시물을 보았습니다.
내가 이전에했던 일은 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
무엇을 비교 하시겠습니까? DB 구조? 또는 DB 구조 및 데이터입니까? –
동일한 열 이름, 열 데이터 형식 및 동일한 행 순서를 가진 경우에만 두 테이블이 동일한 것으로 간주됩니까? – Greg
무엇이 테이블을 비교할 수 없습니까? –