Я ищу способ вернуть динамический список столбцов из соединения LINQ двух таблиц данных.
Во-первых, это не дубликат. Я уже изучил и выбросил:
C # LINQ список динамически выбирает столбцы из объединенного набора данных
Создание LINQ-выбора из нескольких таблиц
Как выполнить соединение LINQ, которое ведет себя точно так же, как физическое внутреннее соединение базы данных?
(и многие другие)
Вот моя отправная точка:
public static DataTable JoinDataTables(DataTable dt1, DataTable dt2, string table1KeyField, string table2KeyField, string[] columns) {
DataTable result = ( from dataRows1 in dt1.AsEnumerable()
join dataRows2 in dt2.AsEnumerable()
on dataRows1.Field<string>(table1KeyField) equals dataRows2.Field<string>(table2KeyField)
[...I NEED HELP HERE with the SELECT....]).CopyToDataTable();
return result;
}
Несколько замечаний и требований:
- Нет движка базы данных. Источниками данных являются большие файлы CSV (500K + записи), которые читаются в c #
DataTable
s.
- Поскольку значения CSV велики, циклически проходить по каждой записи в соединении является плохим решением по соображениям производительности. Я уже пробовал цикл записи, и он слишком медленный. Я получаю отличную производительность при вышеописанном соединении, но не могу найти способ, чтобы оно возвращало только те столбцы, которые я хочу (указанные вызывающей стороной) без циклических записей.
- Если мне нужно перебрать столбцы в соединении, это прекрасно, я просто не хочу зацикливать строки.
- Я хочу иметь возможность передать массив имен столбцов и вернуть только эти столбцы в результирующем
DataTable
. Если обе передаваемые таблицы данных имеют одинаковый столбец, и если этот столбец находится в моем массиве имен столбцов, просто передайте обратно любой столбец, потому что в этом случае данные между двумя столбцами будут одинаковыми.
- Если мне нужно передать 2 массива (1 для каждого желаемого столбца таблицы данных), это нормально, но 1 массив имен столбцов будет идеальным.
- Список столбцов не может быть статическим и жестко закодированным в функцию. Причина в том, что мой
JoinDataTables()
вызывается из разных мест в моей системе, чтобы присоединиться к широкому кругу CSV-файлов, превращаемых в данные, и каждый CSV-файл имеет очень разные столбцы.
- Я не хочу, чтобы все столбцы возвращались в результирующем
DataTable
- только столбцы, которые я указываю в массиве columns
.
Предположим, что перед вызовом JoinDataTables()
у меня есть 2 таблицы данных:
Table: T1
T1A T1B T1C T1D
==================
10 AA H1 Foo1
11 AB H1 Foo2
12 AA H2 Foo1
13 AB H2 Foo2
Table: T2
T2A T2X T2Y T2Z
==================
12 N1 O1 Yeah1
17 N2 O2 Yeah2
18 N3 O1 Yeah1
19 N4 O2 Yeah2
Теперь предположим, что мы объединяем эти 2 таблицы следующим образом:
ON T1.T1A = T2.T2A
select * from [join]
и это дает этот набор результатов:
T1A T1B T1C T1D T2A T2X T2Y T2Z
====================================
12 AA H2 Foo1 12 N1 O1 Yeah1
Обратите внимание, что объединение дает только 1 строку.
Теперь к сути моего вопроса. Предположим, что для данного варианта использования я хочу вернуть только 4 столбца из этого соединения: T1A, T1D, T2A и T2Y. Поэтому мой набор результатов будет выглядеть так:
T1A T1D T2A T2Y
==================
12 Foo1 12 O1
Я хотел бы иметь возможность вызывать мою JoinDataTables
функцию следующим образом:
DataTable dt = JoinDataTables(dt1, dt2, "T1A", "T2A", new string[] {"T1A", "T1D", "T2A", "T2Y"});
С учетом производительности и того факта, что я не хочу перебирать записи (потому что это медленно для больших наборов данных), как это можно сделать? (Объединение уже работает хорошо, теперь мне просто нужен правильный select
сегмент (либо через new{..}
, либо как вы думаете)).
Я не могу принять решение с жестко закодированным списком столбцов внутри функции. Я нашел примеры такого подхода по всему SO
.
Есть идеи?
РЕДАКТИРОВАТЬ: Я буду в порядке, возвращая ВСЕ столбцы каждый раз, но каждая попытка включить все столбцы приводила к некоторому типу FULL OUTER JOIN или CROSS JOIN, возвращая на порядки больше записей чем следует. Итак, я был бы готов вернуть все столбцы, если не получу перекрестное соединение.