动态LINQ其中查询加入其他表

时间:2015-08-28 05:32:30

标签: linq

我有几个表(构建程序时确切的数字是未知的)看起来像这样(行和列的数量可能因表而异):

enter image description here

源数据存储在数据集中。现在我想生成一个新表,其中存储了所有id的所有数据(图片仅显示id 10和20的结果,但目标表应包含所有id的数据):

enter image description here

对此的等效SQLite语句如下所示:

SELECT * FROM Dataset 
JOIN Datensatz2 ON (Dataset.ID=Datensatz2.ID)
JOIN Datensatz3 ON (Datensatz3.ID=Dataset.ID)
JOIN Datensatz4 ON (Datensatz4.ID=Dataset.ID)
WHERE Dataset.Id=10
UNION
SELECT * FROM Dataset 
JOIN Datensatz2 ON (Dataset.ID=Datensatz2.ID)
JOIN Datensatz3 ON (Datensatz3.ID=Dataset.ID)
JOIN Datensatz4 ON (Datensatz4.ID=Dataset.ID)
WHERE Dataset.Id=20
...

之后将删除双id列,因此不必担心。现在的问题是如何将其转换为动态LINQ查询?

2 个答案:

答案 0 :(得分:1)

有很多悬而未决的问题但也许这有助于解决它。由于表格已存储在DataSet中,因此您可以使用Linq-To-DataSetEnumerable.GroupBy按ID进行分组:

var idTables = ds.Tables.Cast<DataTable>().Where(t => t.Columns.Contains("Id"));
if(!idTables.Any()){ MessageBox.Show("No id-tables"); return; }

var idRowGroups = idTables.SelectMany(t => t.AsEnumerable())
    .GroupBy(row => row.Field<int>("Id"))
    .Select(grp => new { ID = grp.Key, Rows = grp });

foreach(var idGroup in idRowGroups)
{
  Console.WriteLine("ID:{0} Rows:{1}"
      , idGroup.ID
      , String.Join(" | ", idGroup.Rows.Select(row => String.Join(",", row.ItemArray))));
}

示例数据:

var ds = new DataSet();
DataTable t1 = new DataTable();
t1.Columns.Add("Id", typeof(int));
t1.Columns.Add("Data", typeof(int));
t1.Rows.Add(1, 1);
t1.Rows.Add(2, 10);
t1.Rows.Add(3, 100);
t1.Rows.Add(4, 1000);
ds.Tables.Add(t1);
t1 = new DataTable();
t1.Columns.Add("Id", typeof(int));
t1.Columns.Add("Data", typeof(int));
t1.Rows.Add(4, 5);
t1.Rows.Add(5, 50);
t1.Rows.Add(7, 500);
t1.Rows.Add(3, 5997);
ds.Tables.Add(t1);
t1 = new DataTable();
t1.Columns.Add("Id", typeof(int));
t1.Columns.Add("Data1", typeof(int));
t1.Columns.Add("Data2", typeof(int));
t1.Rows.Add(1, 5, 0);
t1.Rows.Add(3, 7, 1);
t1.Rows.Add(5, 9, 11);
t1.Rows.Add(7, 11, 222);
ds.Tables.Add(t1);

输出:

ID:1 Rows:1,1 | 1,5,0
ID:2 Rows:2,10
ID:3 Rows:3,100 | 3,5997 | 3,7,1
ID:4 Rows:4,1000 | 4,5
ID:5 Rows:5,50 | 5,9,11
ID:7 Rows:7,500 | 7,11,222

答案 1 :(得分:0)

好吧,我终于做到了,但似乎太复杂了。如果有人能够帮助我改进解决方案,我非常欢迎。

DataSet dsResult = new DataSet();
        var idTables = ds.Tables.Cast<DataTable>().Where(t => t.Columns.Contains("ID"));
        if (!idTables.Any()) { MessageBox.Show("No id-tables"); return; }

        var idRowGroups = idTables.SelectMany(t => t.AsEnumerable())
            .GroupBy(row => row.Field<Int64>("ID"))
            .Select(grp => new { ID = grp.Key, Rows = grp });

        foreach (var idGroup in idRowGroups)
        {
            var liste = idGroup.Rows.ToList();
            for (int i = 0; i < liste.Count; i++)
            {
                if (!dsResult.Tables.Contains(liste[i].Table.TableName))
                {
                    dsResult.Tables.Add(liste[i].Table.TableName);
                    foreach (DataColumn dtCol in liste[i].Table.Columns)
                    {
                        if (dsResult.Tables[liste[i].Table.TableName].Columns.Contains("ID"))
                            dsResult.Tables[liste[i].Table.TableName].Columns.Add(dtCol.ColumnName+i.ToString());
                        else
                        {
                            dsResult.Tables[liste[i].Table.TableName].Columns.Add(dtCol.ColumnName);
                        }
                        dsResult.Tables[liste[i].Table.TableName].Columns[dtCol.ColumnName].DataType = dtCol.DataType;
                    }
                 }
                DataRow dRow = dsResult.Tables[liste[i].Table.TableName].NewRow();
                dRow.ItemArray = liste[i].ItemArray;
                dsResult.Tables[liste[i].Table.TableName].Rows.Add(dRow);
            }

            IEnumerable<IEnumerable<DataRow>> allTablesRows = dsResult.Tables.Cast<DataTable>()
            .Select(table => table.AsEnumerable())
            .CartesianProduct();

            int k = 0;

            foreach (var rows in allTablesRows)
            {
                DataRow zRow = dsErgebnis.Tables[2].NewRow();
                foreach (DataRow dRow in rows)
                {
                    for (int i = 0; i < dRow.ItemArray.Length; i++)
                    {
                        zRow[k] = dRow.ItemArray[i];
                        k++;
                    }
                }
                k = 0;
                dsErgebnis.Tables[2].Rows.Add(zRow);
            }
            dsResult.Clear();
       }

首先我按ID过滤内容。

然后我将结果放在一个新表格中(我在&#39; Datasatz2&#39;数据集中找到ID为10的所有行&#39; ds&#39;例如我放入一个新表格&#39; 39; Datasatz2&#39;在数据集&#39; dsResult&#39;)。

至少我构建了所有表的笛卡尔积,并将其存储在dtaset dsErgebnis中。

结果是我的期望,但如前所述,我对解决方案不满意。