У меня есть такой SQL-запрос (будет параметризован, как только я выполню эту работу):

using (FbCommand cmd = new FbCommand("SELECT MAGACINID, ROBAID, SUM(KOLICINA) AS GOD" + godina.ToString() + " FROM STAVKA WHERE VRDOK = 13 OR VRDOK = 15 GROUP BY MAGACINID, ROBAID ORDER BY ROBAID", con))
                        {
                            using (FbDataAdapter da = new FbDataAdapter(cmd))
                            {
                                DataTable tempDT = new DataTable();
                                if (dt.Rows.Count == 0)
                                {
                                    da.Fill(dt);
                                    continue;
                                }

                                da.Fill(tempDT);

                                var result = dt.AsEnumerable()
                                    .Join(tempDT.AsEnumerable(),
                                    x => new { field1 = x["MAGACINID"], field2 = x["ROBAID"] },
                                    y => new { field1 = y["MAGACINID"], field2 = y["ROBAID"] },
                                    (x, y) => new {
                                        x,
                                        addYear = y["GOD" + godina.ToString()]
                                    });

                                dt = LINQResultToDataTable(result);
                            }
                        }

А вот и метод LINQResultToDataTable()


        private DataTable LINQResultToDataTable<T>(IEnumerable<T> Linqlist)
        {
            DataTable dt = new DataTable();
            PropertyInfo[] allColumns = null;

            if (Linqlist == null) return dt;

            foreach (T Record in Linqlist)
            {
                if (allColumns == null)
                {
                    allColumns = ((Type)Record.GetType()).GetProperties();

                    // Record at position 0 is whole object and needs to be broke into pieces
                    // Record at position 1 is new column

                    foreach (PropertyInfo GetProperty in allColumns)
                    {
                        Type colType = GetProperty.PropertyType;

                        if ((colType.IsGenericType) && (colType.GetGenericTypeDefinition()
                               == typeof(Nullable<>)))
                        {
                            colType = colType.GetGenericArguments()[0];
                        }

                        dt.Columns.Add(new DataColumn(GetProperty.Name, colType));
                    }
                }

                DataRow dr = dt.NewRow();

                foreach (PropertyInfo pinfo in allColumns)
                {
                    dr[pinfo.Name] = pinfo.GetValue(Record, null) == null ? DBNull.Value : pinfo.GetValue
                           (Record, null);
                }

                dt.Rows.Add(dr);
            }
            return dt;
        }

Первая заливка данных в порядке, и она заполняет ее следующими столбцами:

MagacinID
RobaID
God2021

Теперь, когда я пытаюсь присоединиться к новой таблице с помощью linq, мне нужно только добавить God2020 в качестве нового столбца. Проблема в том, что когда я создаю вывод linq, я не могу сказать ему разбить объект x на столбцы, но мне нужно взять его целиком, поэтому результат linq выглядит следующим образом:

x (this one have ItemArray with all columns)
God2020

И новый datatable выглядит так же.

Я пытался сделать это внутри метода LINQResultToDataTable, чтобы взять 0th элемент Result и разбить его на столбцы, добавить в datatable, добавить новый (1-й элемент) и заполнить его (см. Комментарий в этот метод), но я застрял и не знаю, как это сделать. У кого-нибудь есть решение?

Изменить: я не ясно дал понять, поэтому вот еще объяснение.

У меня есть цикл foreach, который проходит через 5 databases, и внутри этого цикла foreach находится этот код.

Первая база данных возвращает эти столбцы

MagacinID
RobaID
God2021

Второй

MagacinID
RobaID
God2020

Третий

MagacinID
RobaID
God2019

Четвертый

MagacinID
RobaID
God2018

Пятый

MagacinID
RobaID
God2017

Я хочу, чтобы все это было объединено в одну таблицу данных в столбцах MagacinID AND RobaID следующим образом:

MagacinID
RobaID
God2021
God2020
God2019
God2018
God2017
0
Aleksa Ristic 26 Ноя 2021 в 20:18
Думаю, ваш вопрос неполный. Не относясь к вашему вопросу, лично я не буду использовать linQ для этого, я постараюсь решить такие проблемы на уровне БД.
 – 
Leandro Bardelli
26 Ноя 2021 в 20:25
Проблема в том, что я меняю строку подключения (разные базы данных), поэтому я не могу сделать это на уровне БД.
 – 
Aleksa Ristic
26 Ноя 2021 в 20:40
Вы можете сделать ссылку на БД. Но я думаю, вам нужно отредактировать свой вопрос, потому что заканчивается "вот так:" и не более того.
 – 
Leandro Bardelli
26 Ноя 2021 в 20:49
1
Извините, поправил .. Это была просто заметка.
 – 
Aleksa Ristic
26 Ноя 2021 в 20:54
2
Я запутался - вы заполняете таблицу данных из своего запроса, а затем проецируете ее на анонимные типы только для того, чтобы вернуть ее обратно в качестве таблицы данных?
 – 
D Stanley
26 Ноя 2021 в 21:00

1 ответ

Лучший ответ

Под слиянием я подразумеваю использование слияния DataTable, которое в основном делает что-то вроде полного внешнего соединения для объявленных полей PK в таблице данных, а затем делает объединенную таблицу результатом соединения;

        var d1 = new DataTable();
        d1.Columns.Add("SomeId");
        d1.Columns.Add("Col1");

        d1.Rows.Add("ID1", "Col1Val1");
        d1.Rows.Add("ID2", "Col1Val2");
        d1.PrimaryKey = new[] { d1.Columns["SomeId"] };



        var d2 = new DataTable();
        d2.Columns.Add("SomeId");
        d2.Columns.Add("Col2");

        d2.Rows.Add("ID1", "Col2Val1");
        d2.Rows.Add("ID3", "Col2Val2");
        d2.PrimaryKey = new[] { d2.Columns["SomeId"] };



        var d3 = new DataTable();
        d3.Columns.Add("SomeId");
        d3.Columns.Add("Col3");

        d3.Rows.Add("ID2", "Col3Val1");
        d3.Rows.Add("ID3", "Col3Val2");
        d3.PrimaryKey = new[] { d3.Columns["SomeId"] };


        d1.Merge(d2, false, MissingSchemaAction.Add);
        d1.Merge(d3, false, MissingSchemaAction.Add);

Вот к чему приводит приведенный выше код:

enter image description here

D1 начинался с двух столбцов, затем во время первого слияния он добавлялся в третий (Col2), и значения из столбца Col2 d2 были помещены в столбец Col2 d1, совпадая по столбцу PK (SomeId).

Затем во время второго слияния к d1 (Col3) был добавлен четвертый столбец, а значения из Col3 в d3 скопированы в d1.

Вы заметите, что я намеренно установил для d2 разные значения PK с d1, поэтому добавляются не только новые столбцы, но и новые строки.

Эта вторая операция слияния не добавила новых строк (у d1 уже были ID1, ID2 и ID3)

1
Caius Jard 26 Ноя 2021 в 22:01
В моей проблеме у меня не PK, а UNIQUE(MAGACINID, ROBAID)
 – 
Aleksa Ristic
27 Ноя 2021 в 00:21
О, я узнал, как добавить несколько первичных ключей ... Думаю, это решит мою проблему
 – 
Aleksa Ristic
27 Ноя 2021 в 00:29
d2.PrimaryKey = new[] { d2.Columns["SomeId"], d2.Columns["SomeOtherId"] };
 – 
Caius Jard
27 Ноя 2021 в 00:36
Это сработало. Спасибо.
 – 
Aleksa Ristic
27 Ноя 2021 в 04:21