Ответ 1
Вы можете попробовать следующий код...
table1.AsEnumerable().Where(
r =>!table2.AsEnumerable().Select(x=>x["ID"]).ToList().Contains(r["ID"])).ToList();
У меня эти два типа данных, и я хочу получить разницу между ними. Вот пример:
Table1
-------------------------
ID | Name
--------------------------
1 | A
2 | B
3 | C
--------------------------
Table2
-------------------------
ID | Name
--------------------------
1 | A
2 | B
--------------------------
Мне просто нужен результат как данные, которые находятся в таблице1, а не в таблице2 (table1-table2)
ResultTable
-------------------------
ID | Name
--------------------------
3 | C
--------------------------
Я попытался использовать эти два подобных решения через Linq, но всегда возвращает table1, а не table1-table2. Вот первое решение:
DataTable table1= ds.Tables["table1"];
DataTable table2= ds.Tables["table2"];
var diff= table1.AsEnumerable().Except(table2.AsEnumerable(),DataRowComparer.Default);
Второе решение:
var dtOne = table1.AsEnumerable();
var dtTwo = table2.AsEnumerable();
var difference = dtOne.Except(dtTwo);
Итак, где ошибка? Большое вам спасибо за все ваши ответы.:)
Вы можете попробовать следующий код...
table1.AsEnumerable().Where(
r =>!table2.AsEnumerable().Select(x=>x["ID"]).ToList().Contains(r["ID"])).ToList();
Я просто прошел через это и хотел поделиться своими выводами. Для моего приложения это механизм синхронизации данных, но я думаю, вы увидите, как это относится к исходному вопросу.
В моем случае у меня был DataTable
, который представлял мою загрузку данных last и в будущем, мне нужно получить состояние current данных и загружайте только различия.
// get the Current state of the data
DataTable dtCurrent = GetCurrentData();
// get the Last uploaded data
DataTable dtLast = GetLastUploadData();
dtLast.AcceptChanges();
// the table meant to hold only the differences
DataTable dtChanges = null;
// merge the Current DataTable into the Last DataTable,
// with preserve changes set to TRUE
dtLast.Merge(dtCurrent, true);
// invoke GetChanges() with DataRowState.Unchanged
// !! this is the key !!
// the rows with RowState == DataRowState.Unchanged
// are the differences between the 2 tables
dtChanges = dtLast.GetChanges(DataRowState.Unchanged);
Надеюсь, это поможет. Я боролся с этим в течение нескольких часов и обнаружил множество ложных проводов в interwebz и закончил сравнение RowStates
после слияния нескольких разных способов.
Я попытаюсь сделать это на уровне столбца, а не в DataTable.
IEnumerable<int> id_table1 = table1.AsEnumerable().Select(val=> (int)val["ID"]);
IEnumerable<int> id_table2 = table2.AsEnumerable().Select(val=> (int)val["ID"]);
IEnumerable<int> id_notinTable1= id_table2.Except(id_table1);
Просто добавив .Select()
к вашему ответу...
Попробуйте это
DataTable dtmismatch = Table1.AsEnumerable().Except(Table2.AsEnumerable(), DataRowComparer.Default).CopyToDataTable<DataRow>();
Попробуйте ниже, это довольно просто. Объедините два набора вместе и получите разницу. Если настройки не совпадают, это не сработает. Попытка проверить те же
DataSet firstDsData = new DataSet();
DataSet secondDsData = new DataSet();
DataSet finalDsData = new DataSet();
DataSet DifferenceDataSet = new DataSet();
finalDsData.Merge(firstDsData);
finalDsData.AcceptChanges();
finalDsData.Merge(secondDsData);
DifferenceDataSet = finalDsData.GetChanges();
Попробуйте подход ниже:
Инициализация:
var columnId = new DataColumn("ID", typeof (int));
var columnName = new DataColumn("Name", typeof (string));
var table1 = new DataTable();
table1.Columns.AddRange(new[] {columnId, columnName});
table1.PrimaryKey = new[] {columnId};
table1.Rows.Add(1, "A");
table1.Rows.Add(2, "B");
table1.Rows.Add(3, "C");
var table2 = table1.Clone();
table2.Rows.Add(1, "A");
table2.Rows.Add(2, "B");
table2.Rows.Add(4, "D");
Решение:
var table3 = table1.Copy();
table3.AcceptChanges();
table3.Merge(table2);
var distinctRows = from row in table3.AsEnumerable()
where row.RowState != DataRowState.Modified
select row;
var distintTable = distinctRows.CopyToDataTable();
Выше решение также работает, когда в таблице 2 есть новые строки, которых нет в таблице 1.
distintTable
содержит C и D.
Попробуйте ниже, это довольно просто. Объедините два набора вместе и получите разницу. Если настройки не совпадают, это не сработает.
DataSet firstDsData = new DataSet();
DataSet secondDsData = new DataSet();
DataSet finalDsData = new DataSet();
DataSet DifferenceDataSet = new DataSet();
finalDsData.Merge(firstDsData);
finalDsData.AcceptChanges();
finalDsData.Merge(secondDsData);
DifferenceDataSet = finalDsData.GetChanges();
Try This ...
public DataTable getDiffRecords(DataTable dtDataOne, DataTable dtDataTwo)
{
DataTable returnTable = new DataTable("returnTable");
using (DataSet ds = new DataSet())
{
ds.Tables.AddRange(new DataTable[] { dtDataOne.Copy(), dtDataTwo.Copy() });
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];
}
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);
for (int i = 0; i < dtDataOne.Columns.Count; i++)
{
returnTable.Columns.Add(dtDataOne.Columns[i].ColumnName, dtDataOne.Columns[i].DataType);
}
returnTable.BeginLoadData();
foreach (DataRow parentrow in ds.Tables[0].Rows)
{
DataRow[] childrows = parentrow.GetChildRows(r1);
if (childrows == null || childrows.Length == 0)
returnTable.LoadDataRow(parentrow.ItemArray, true);
}
foreach (DataRow parentrow in ds.Tables[1].Rows)
{
DataRow[] childrows = parentrow.GetChildRows(r2);
if (childrows == null || childrows.Length == 0)
returnTable.LoadDataRow(parentrow.ItemArray, true);
}
returnTable.EndLoadData();
}
return returnTable;
}