我有2个数据表,我只想知道它们是否相同。 “相同”,我的意思是它们具有完全相同的行数,每列中的数据完全相同或不相同。我想写(找到)一个接受两个表并返回一个布尔值的方法。
如何以这种方式比较2个数据表?两者都有相同的模式。
答案 0 :(得分:20)
public static bool AreTablesTheSame( DataTable tbl1, DataTable tbl2)
{
if (tbl1.Rows.Count != tbl2.Rows.Count || tbl1.Columns.Count != tbl2.Columns.Count)
return false;
for ( int i = 0; i < tbl1.Rows.Count; i++)
{
for ( int c = 0; c < tbl1.Columns.Count; c++)
{
if (!Equals(tbl1.Rows[i][c] ,tbl2.Rows[i][c]))
return false;
}
}
return true;
}
答案 1 :(得分:10)
如果您将DataTable作为函数返回,您可以:
DataTable dataTable1; // Load with data
DataTable dataTable2; // Load with data (same schema)
// Fast check for row count equality.
if ( dataTable1.Rows.Count != dataTable2.Rows.Count) {
return true;
}
var differences =
dataTable1.AsEnumerable().Except(dataTable2.AsEnumerable(),
DataRowComparer.Default);
return differences.Any() ? differences.CopyToDataTable() : new DataTable();
答案 2 :(得分:7)
您需要循环遍历每个表的行,然后遍历该循环中的每个列以比较各个值。
这里有一个代码示例:http://canlu.blogspot.com/2009/05/how-to-compare-two-datatables-in-adonet.html
答案 3 :(得分:5)
OP,MAW74656最初在问题正文中将此回答发布在accepted answer上,如this comment中所述:
我使用了这个并编写了一个公共方法来调用代码并返回布尔值。
OP的回答:
使用的代码:
public bool tablesAreTheSame(DataTable table1, DataTable table2) { DataTable dt; dt = getDifferentRecords(table1, table2); if (dt.Rows.Count == 0) return true; else return false; } //Found at http://canlu.blogspot.com/2009/05/how-to-compare-two-datatables-in-adonet.html private DataTable getDifferentRecords(DataTable FirstDataTable, DataTable SecondDataTable) { //Create Empty Table DataTable ResultDataTable = new DataTable("ResultDataTable"); //use a Dataset to make use of a DataRelation object using (DataSet ds = new DataSet()) { //Add tables ds.Tables.AddRange(new DataTable[] { FirstDataTable.Copy(), SecondDataTable.Copy() }); //Get Columns for DataRelation DataColumn[] firstColumns = new DataColumn[ds.Tables[0].Columns.Count]; for (int i = 0; i < firstColumns.Length; i++) { firstColumns[i] = ds.Tables[0].Columns[i]; } DataColumn[] secondColumns = new DataColumn[ds.Tables[1].Columns.Count]; for (int i = 0; i < secondColumns.Length; i++) { secondColumns[i] = ds.Tables[1].Columns[i]; } //Create DataRelation DataRelation r1 = new DataRelation(string.Empty, firstColumns, secondColumns, false); ds.Relations.Add(r1); DataRelation r2 = new DataRelation(string.Empty, secondColumns, firstColumns, false); ds.Relations.Add(r2); //Create columns for return table for (int i = 0; i < FirstDataTable.Columns.Count; i++) { ResultDataTable.Columns.Add(FirstDataTable.Columns[i].ColumnName, FirstDataTable.Columns[i].DataType); } //If FirstDataTable Row not in SecondDataTable, Add to ResultDataTable. ResultDataTable.BeginLoadData(); foreach (DataRow parentrow in ds.Tables[0].Rows) { DataRow[] childrows = parentrow.GetChildRows(r1); if (childrows == null || childrows.Length == 0) ResultDataTable.LoadDataRow(parentrow.ItemArray, true); } //If SecondDataTable Row not in FirstDataTable, Add to ResultDataTable. foreach (DataRow parentrow in ds.Tables[1].Rows) { DataRow[] childrows = parentrow.GetChildRows(r2); if (childrows == null || childrows.Length == 0) ResultDataTable.LoadDataRow(parentrow.ItemArray, true); } ResultDataTable.EndLoadData(); } return ResultDataTable; }
答案 4 :(得分:3)
尝试将linq用于数据集
(from b in table1.AsEnumerable()
select new { id = b.Field<int>("id")}).Except(
from a in table2.AsEnumerable()
select new {id = a.Field<int>("id")})
答案 5 :(得分:2)
我得到了如何比较2个dataTables的解决方案
http://microsoftdotnetsolutions.blogspot.in/2012/12/compare-two-datatables.html
答案 6 :(得分:1)
如果您在数据库中有表,则可以进行完全外连接以获得差异。例如:
select t1.Field1, t1.Field2, t2.Field1, t2.Field2
from Table1 t1
full outer join Table2 t2 on t1.Field1 = t2.Field1 and t1.Field2 = t2.Field2
where t1.Field1 is null or t2.Field2 is null
过滤掉所有相同的记录。在前两个或最后两个字段中有数据,具体取决于记录来自哪个表。
答案 7 :(得分:1)
/// <summary>
/// https://stackoverflow.com/a/45620698/2390270
/// Compare a source and target datatables and return the row that are the same, different, added, and removed
/// </summary>
/// <param name="dtOld">DataTable to compare</param>
/// <param name="dtNew">DataTable to compare to dtOld</param>
/// <param name="dtSame">DataTable that would give you the common rows in both</param>
/// <param name="dtDifferences">DataTable that would give you the difference</param>
/// <param name="dtAdded">DataTable that would give you the rows added going from dtOld to dtNew</param>
/// <param name="dtRemoved">DataTable that would give you the rows removed going from dtOld to dtNew</param>
public static void GetTableDiff(DataTable dtOld, DataTable dtNew, ref DataTable dtSame, ref DataTable dtDifferences, ref DataTable dtAdded, ref DataTable dtRemoved)
{
try
{
dtAdded = dtOld.Clone();
dtAdded.Clear();
dtRemoved = dtOld.Clone();
dtRemoved.Clear();
dtSame = dtOld.Clone();
dtSame.Clear();
if (dtNew.Rows.Count > 0) dtDifferences.Merge(dtNew.AsEnumerable().Except(dtOld.AsEnumerable(), DataRowComparer.Default).CopyToDataTable<DataRow>());
if (dtOld.Rows.Count > 0) dtDifferences.Merge(dtOld.AsEnumerable().Except(dtNew.AsEnumerable(), DataRowComparer.Default).CopyToDataTable<DataRow>());
if (dtOld.Rows.Count > 0 && dtNew.Rows.Count > 0) dtSame = dtOld.AsEnumerable().Intersect(dtNew.AsEnumerable(), DataRowComparer.Default).CopyToDataTable<DataRow>();
foreach (DataRow row in dtDifferences.Rows)
{
if (dtOld.AsEnumerable().Any(r => Enumerable.SequenceEqual(r.ItemArray, row.ItemArray))
&& !dtNew.AsEnumerable().Any(r => Enumerable.SequenceEqual(r.ItemArray, row.ItemArray)))
{
dtRemoved.Rows.Add(row.ItemArray);
}
else if (dtNew.AsEnumerable().Any(r => Enumerable.SequenceEqual(r.ItemArray, row.ItemArray))
&& !dtOld.AsEnumerable().Any(r => Enumerable.SequenceEqual(r.ItemArray, row.ItemArray)))
{
dtAdded.Rows.Add(row.ItemArray);
}
}
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
}
}
答案 8 :(得分:0)
没有什么可以为你做这件事;你要实现这一目标的唯一方法是迭代所有行/列并将它们相互比较。
答案 9 :(得分:0)
或者这个,我没有实现数组比较所以你也会有一些乐趣:)
public bool CompareTables(DataTable a, DataTable b)
{
if(a.Rows.Count != b.Rows.Count)
{
// different size means different tables
return false;
}
for(int rowIndex=0; rowIndex<a.Rows.Count; ++rowIndex)
{
if(!arraysHaveSameContent(a.Rows[rowIndex].ItemArray, b.Rows[rowIndex].ItemArray,))
{
return false;
}
}
// Tables have same data
return true;
}
private bool arraysHaveSameContent(object[] a, object[] b)
{
// Here your super cool method to compare the two arrays with LINQ,
// or if you are a loser do it with a for loop :D
}
答案 10 :(得分:0)
如果您正在使用DataTable,那么您可以将比较两个'DataTable'的DataTable与原始数据进行比较时加载AKA DataTable.GetChanges Method (DataRowState)
答案 11 :(得分:0)
受到充满讽刺意味的使用 DataRowComparer.Default 的回答的启发,但只需要比较DataTable中列的子集的东西,我做了一个 DataTableComparer < / strong>对象,您可以在其中指定在比较中使用哪些列。如果它们具有不同的色谱柱/方案,则特别好。
DataRowComparer.Default 起作用是因为它实现了IEqualityComparer。然后,我创建了一个对象,您可以在其中定义将比较DataRow的哪些列。
public class DataTableComparer : IEqualityComparer<DataRow>
{
private IEnumerable<String> g_TestColumns;
public void SetCompareColumns(IEnumerable<String> p_Columns)
{
g_TestColumns = p_Columns;
}
public bool Equals(DataRow x, DataRow y)
{
foreach (String sCol in g_TestColumns)
if (!x[sCol].Equals(y[sCol])) return false;
return true;
}
public int GetHashCode(DataRow obj)
{
StringBuilder hashBuff = new StringBuilder();
foreach (String sCol in g_TestColumns)
hashBuff.AppendLine(obj[sCol].ToString());
return hashBuff.ToString().GetHashCode();
}
}
您可以通过以下方式使用它:
DataTableComparer comp = new DataTableComparer();
comp.SetCompareColumns(new String[] { "Name", "DoB" });
DataTable celebrities = SomeDataTableSource();
DataTable politicians = SomeDataTableSource2();
List<DataRow> celebrityPoliticians = celebrities.AsEnumerable().Intersect(politicians.AsEnumerable(), comp).ToList();
答案 12 :(得分:0)
合并两个数据表然后比较更改如何?不确定是否能满足您100%的需求,但为了快速比较它是否能胜任。
public DataTable GetTwoDataTablesChanges(DataTable firstDataTable, DataTable secondDataTable)
{
firstDataTable.Merge(secondDataTable);
return secondDataTable.GetChanges();
}
您可以了解有关DataTable.Merge()的更多信息