Home > Enterprise >  Linq to datatable with unknown columns
Linq to datatable with unknown columns

Time:11-27

I am having SQL query like this (will be parametrized once I make this work):

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

And here is LINQResultToDataTable() method


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

First datatable fill is okay and it fills it with these columns:

MagacinID
RobaID
God2021

Now when I try to join new table using linq I should only add God2020 as new column. Problem is that when I am creating output of linq I cannot tell it to break x object into columns but I need to take it whole so linq result looks like this:

x (this one have ItemArray with all columns)
God2020

And new datatable looks same.

What I tried doing is inside LINQResultToDataTable method to take 0th element of Result and break it into columns, add to datatable, add new one (1st element) and populate it (see comment in that method) but I am stuck and do not know how to do that. Anyone have any solution?

Edit: I made it not clear so here is more explanation.

I have foreach loop which loops through 5 databases and inside that foreach loop is this code.

First database returns these columns

MagacinID
RobaID
God2021

Second

MagacinID
RobaID
God2020

Third

MagacinID
RobaID
God2019

Fourth

MagacinID
RobaID
God2018

Fifth

MagacinID
RobaID
God2017

I want all this merged into one datatable on columns MagacinID AND RobaID like this:

MagacinID
RobaID
God2021
God2020
God2019
God2018
God2017

CodePudding user response:

By Merge, I mean use the DataTable merge, which basically does something like a full outer join on declared PK fields in a datatable, and then makes the merged-into table the result of the join;

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

Here's what the above code leads to:

enter image description here

d1 started off with two columns, then during the first Merge it added in a third (Col2), and the values from d2's Col2 were put into d1's Col2, matching on the PK column (SomeId).

Then during the second Merge a fourth column was added to d1 (Col3), and the values out of Col3 in d3 copied into d1.

You'll notice that I deliberately made d2 have different PK values to d1, so not only do new columns get added, but new rows get added too

No new rows were added by this second merge op (d1 already had an ID1, ID2 and ID3)

  • Related