Подтвердить что ты не робот

Как получить разницу между двумя таблицами данных

У меня эти два типа данных, и я хочу получить разницу между ними. Вот пример:

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);

Итак, где ошибка? Большое вам спасибо за все ваши ответы.:)

4b9b3361

Ответ 1

Вы можете попробовать следующий код...

table1.AsEnumerable().Where(
    r =>!table2.AsEnumerable().Select(x=>x["ID"]).ToList().Contains(r["ID"])).ToList();

Ответ 2

Я просто прошел через это и хотел поделиться своими выводами. Для моего приложения это механизм синхронизации данных, но я думаю, вы увидите, как это относится к исходному вопросу.

В моем случае у меня был 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 после слияния нескольких разных способов.

Ответ 3

Я попытаюсь сделать это на уровне столбца, а не в 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() к вашему ответу...

Ответ 4

Попробуйте это

DataTable dtmismatch = Table1.AsEnumerable().Except(Table2.AsEnumerable(), DataRowComparer.Default).CopyToDataTable<DataRow>();

Ответ 5

Попробуйте ниже, это довольно просто. Объедините два набора вместе и получите разницу. Если настройки не совпадают, это не сработает. Попытка проверить те же

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();

Ответ 6

Попробуйте подход ниже:

Инициализация:

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.

Ответ 7

Попробуйте ниже, это довольно просто. Объедините два набора вместе и получите разницу. Если настройки не совпадают, это не сработает.

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();

Ответ 8

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;
    }