我有2個數據表,我只是想知道它們是否相同。 「相同」,我的意思是他們有完全相同數量的行,每列中的數據完全相同,或者沒有。我很想寫(找到)接受兩個表並返回一個布爾值的方法。如何比較2個數據表
如何以這種方式比較2個數據表?兩者都有相同的模式。
我有2個數據表,我只是想知道它們是否相同。 「相同」,我的意思是他們有完全相同數量的行,每列中的數據完全相同,或者沒有。我很想寫(找到)接受兩個表並返回一個布爾值的方法。如何比較2個數據表
如何以這種方式比較2個數據表?兩者都有相同的模式。
您需要循環遍歷每個表的行,然後遍歷該循環內的每個列以比較各個值。
有一個代碼示例在這裏:http://canlu.blogspot.com/2009/05/how-to-compare-two-datatables-in-adonet.html
- 我用它並寫了一個公共方法來調用代碼並返回布爾值。請參閱編輯使用的代碼。 – MAW74656
沒有什麼會爲你做到這一點;要實現這一點,唯一的方法是迭代所有行/列並將它們相互比較。
- .NET的下一個版本將包括一個DataTable.CompareTo(DataTable)方法來爲我們處理這個問題。 – MAW74656
如果在數據庫中的表,你可以做一個完全外部連接,以獲得差異。例如:
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
所有記錄是相同的被過濾掉。在前兩個或後兩個字段中都有數據,具體取決於記錄來自哪個表。
- 我想在不涉及SQL服務器的情況下進行比較(嘗試保存到DB的往返行程),因此在這種情況下這不適合我。 – MAW74656
儘量讓使用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")})
- 我沒有在問題中指定這個(因此+1),但我想避免LINQ,所以我可以在.NET 2.0的工作站上運行。是的,它的跛腳,但它的一種要求。 – MAW74656
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;
}
- 是的,我明白這可以如何工作。我可能會看到它是否比其他選項快。 PizzaTime! – MAW74656
代碼不可編譯,也應該使用!Equals而不是'!='運算符。查看帖子http://geekswithblogs.net/mnf/archive/2013/08/27/methods-to-verify-are-datatables-or-datasets-the-same.aspx –
或此,我並沒有實現數組對比,所以你也會有一些樂趣:)
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
}
*嘆息我需要學習linq –
感謝小修正;-) –
@Davide Piras -Loser的使用循環?如果你針對比.NET 3.5更低的東西進行編程會怎樣?這是一個苛刻的人。 – MAW74656
那麼,如果你使用的是數據表在所有然後,而不是比較兩個「大taTables'你能不能只比較這都將有與原始數據的變化,當它被裝AKA DataTable.GetChanges Method (DataRowState)
的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; }
我得到了如何比較2個數據表的解決方案是
http://microsoftdotnetsolutions.blogspot.in/2012/12/compare-two-datatables.html
如果您正在返回一個DataTable作爲一個功能你可以:
DataTable dataTable1; // Load with data
DataTable dataTable2; // Load with data (same schema)
var differences =
dataTable1.AsEnumerable().Except(dataTable2.AsEnumerable(),
DataRowComparer.Default);
return differences.Any() ? differences.CopyToDataTable() : new DataTable();
/// <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());
}
}
這已經在這裏問:http://stackoverflow.com/questions/164144/c-how-to-compare-two -datatables -ab-how-to-show-rows-which-in-b-but-not問題並不完全相同。在你的情況下,你需要遍歷行,並在該循環內循環遍歷行中的列來比較值。 – David
@DavidStratton -Sorry,這不是同一個問題。 – MAW74656
想要這樣做的目的是爲了給它一些背景? – Coops