Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 完全外部联接,在2个数据表上,具有列列表_C#_.net_Linq_Ado.net - Fatal编程技术网

C# 完全外部联接,在2个数据表上,具有列列表

C# 完全外部联接,在2个数据表上,具有列列表,c#,.net,linq,ado.net,C#,.net,Linq,Ado.net,我有两个数据表,我不知道它们的数据列列表。此列表必须在运行时提取,并用于完全外部联接 当使用这些列时,两个表之间的列需要合并,我需要显示所有数据 到目前为止,我所做的是 使用intersect获取公共列,并实现IEqualityComparer 使用这些列创建一个新的datatable,以便将这两个datatable合并到此新表中 然而,在第二步中,我与Linq有问题 到目前为止,我有: 获取公共列 // Get common columns var commonColumns = dt

我有两个数据表,我不知道它们的数据列列表。此列表必须在运行时提取,并用于完全外部联接

当使用这些列时,两个表之间的列需要合并,我需要显示所有数据

到目前为止,我所做的是

  • 使用intersect获取公共列,并实现IEqualityComparer
  • 使用这些列创建一个新的datatable,以便将这两个datatable合并到此新表中
  • 然而,在第二步中,我与Linq有问题

    到目前为止,我有:

    获取公共列

    // Get common columns var commonColumns = dt1.Columns.OfType().Intersect(dt2.Columns.OfType(), new DataColumnComparer()); // Create the result which is going to be sent to the user DataTable result = new DataTable(); // Add all the columns from both tables result.Columns.AddRange( dt1.Columns.OfType() .Union(dt2.Columns.OfType(), new DataColumnComparer()) .Select(c => new DataColumn(c.Caption, c.DataType, c.Expression, c.ColumnMapping)).ToArray()); //获取公共列 var commonColumns=dt1.Columns.OfType().Intersect(dt2.Columns.OfType(),new datacolumncomperator()); 创建新数据表

    // Get common columns var commonColumns = dt1.Columns.OfType().Intersect(dt2.Columns.OfType(), new DataColumnComparer()); // Create the result which is going to be sent to the user DataTable result = new DataTable(); // Add all the columns from both tables result.Columns.AddRange( dt1.Columns.OfType() .Union(dt2.Columns.OfType(), new DataColumnComparer()) .Select(c => new DataColumn(c.Caption, c.DataType, c.Expression, c.ColumnMapping)).ToArray()); //创建要发送给用户的结果 DataTable结果=新DataTable(); //添加两个表中的所有列 result.Columns.AddRange( dt1.Columns.OfType() .Union(dt2.Columns.OfType(),新的DataColumnComparer()) .Select(c=>newdatacolumn(c.Caption,c.DataType,c.Expression,c.ColumnMapping)).ToArray();
    如何从运行时提取的数据列列表中动态获得有效的完整外部联接?

    我也在努力获得答案,我正在复制粘贴整个代码。我相信这会对你有所帮助

    您只需要执行此联接的两个表的
    DataTable1
    DataTable2
    primarykeys
    。您可以将datatable主键设置为

    datatable1.PrimaryKey = new DataColumn[] { captureDT.Columns["Your Key Name"] };
    
    //你的代码

    /// <summary>
        /// Combines the data of two data table into a single data table. The grouping of tables
        /// will be based on the primary key provided for both the tables.
        /// </summary>
        /// <param name="table1"></param>
        /// <param name="table2"></param>
        /// <param name="table1PrimaryKey"></param>
        /// <param name="table2PrimaryKey"></param>
        /// <returns></returns>
        private DataTable DataTablesOuterJoin(DataTable table1, DataTable table2, string table1PrimaryKey, string table2PrimaryKey)
        {
            DataTable flatDataTable = new DataTable();
    
            foreach (DataColumn column in table2.Columns)
            {
                flatDataTable.Columns.Add(new DataColumn(column.ToString()));
            }
            foreach (DataColumn column in table1.Columns)
            {
                flatDataTable.Columns.Add(new DataColumn(column.ToString()));
            }
    
            // Retrun empty table with required columns to generate empty extract
            if (table1.Rows.Count <= 0 && table2.Rows.Count <= 0)
            {
                flatDataTable.Columns.Remove(table2PrimaryKey);
                return flatDataTable;
            }
    
            var dataBaseTable2 = table2.AsEnumerable();
            var groupDataT2toT1 = dataBaseTable2.GroupJoin(table1.AsEnumerable(),
                                    br => new { id = br.Field<string>(table2PrimaryKey).Trim().ToLower() },
                                    jr => new { id = jr.Field<string>(table1PrimaryKey).Trim().ToLower() },
                                    (baseRow, joinRow) => joinRow.DefaultIfEmpty()
                                        .Select(row => new
                                        {
                                            flatRow = baseRow.ItemArray.Concat((row == null) ? new object[table1.Columns.Count] :
                                            row.ItemArray).ToArray()
                                        })).SelectMany(s => s);
    
            var dataBaseTable1 = table1.AsEnumerable();
            var groupDataT1toT2 = dataBaseTable1.GroupJoin(table2.Select(),
                                    br => new { id = br.Field<string>(table1PrimaryKey).Trim().ToLower() },
                                    jr => new { id = jr.Field<string>(table2PrimaryKey).Trim().ToLower() },
                                    (baseRow, joinRow) => joinRow.DefaultIfEmpty()
                                        .Select(row => new
                                        {
                                            flatRow = (row == null) ? new object[table2.Columns.Count].ToArray().Concat(baseRow.ItemArray).ToArray() :
                                            row.ItemArray.Concat(baseRow.ItemArray).ToArray()
                                        })).SelectMany(s => s);
    
            // Get the union of both group data to single set
            groupDataT2toT1 = groupDataT2toT1.Union(groupDataT1toT2);
    
            // Load the grouped data to newly created table 
            foreach (var result in groupDataT2toT1)
            {
                flatDataTable.LoadDataRow(result.flatRow, false);
            }
    
            // Get the distinct rows only
            IEnumerable rows = flatDataTable.Select().Distinct(DataRowComparer.Default);
    
            // Create a new distinct table with same structure as flatDataTable
            DataTable distinctFlatDataTable = flatDataTable.Clone();
            distinctFlatDataTable.Rows.Clear();
    
            // Push all the rows into distinct table.
            // Note: There will be two different columns for primary key1 and primary key2. In grouped rows,
            // primary key1 or primary key2 can have empty values. So copy all the primary key2 values to
            // primary key1 only if primary key1 value is empty and then delete the primary key2. So at last
            // we will get only one perimary key. Please make sure the non-deleted key must be present in 
            foreach (DataRow row in rows)
            {
                if (string.IsNullOrEmpty(row[table1PrimaryKey].ToString()))
                    row[table1PrimaryKey] = row[table2PrimaryKey];
    
                if (string.IsNullOrEmpty(row[CaptureBusDateColumn].ToString()))
                    row[CaptureBusDateColumn] = _businessDate;
    
                if (string.IsNullOrEmpty(row[CaptureUserIDColumn].ToString()))
                    row[CaptureUserIDColumn] = row[StatsUserIDColumn];
    
                distinctFlatDataTable.ImportRow(row);
            }
    
            // Sort the table based on primary key.
            DataTable sortedFinaltable = (from orderRow in distinctFlatDataTable.AsEnumerable()
                                          orderby orderRow.Field<string>(table1PrimaryKey)
                                          select orderRow).CopyToDataTable();
    
            // Remove primary key2 as we have already copied it to primary key1 
            sortedFinaltable.Columns.Remove(table2PrimaryKey);
    
            return ReplaceNulls(sortedFinaltable, "0");
        }
    
        /// <summary>
        /// Replace all the null values from data table with specified string 
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="replaceStr"></param>
        /// <returns></returns>
        private DataTable ReplaceNulls(DataTable dt, string replaceStr)
        {
            for (int a = 0; a < dt.Rows.Count; a++)
            {
                for (int i = 0; i < dt.Columns.Count; i++)
                {
                    if (dt.Rows[a][i] == DBNull.Value)
                    {
                        dt.Rows[a][i] = replaceStr;
                    }
                }
            }
            return dt;
        }
    
    //
    ///将两个数据表的数据合并为一个数据表。表的分组
    ///将基于为两个表提供的主键。
    /// 
    /// 
    /// 
    /// 
    /// 
    /// 
    专用DataTable DataTableOuterJoin(DataTable1、DataTable2、string table1 PrimaryKey、string table2 PrimaryKey)
    {
    DataTable flatDataTable=新DataTable();
    foreach(表2中的DataColumn列。列)
    {
    flatDataTable.Columns.Add(新数据列(column.ToString());
    }
    foreach(表1.Columns中的DataColumn列)
    {
    flatDataTable.Columns.Add(新数据列(column.ToString());
    }
    //使用所需列重新运行空表以生成空提取
    如果(table1.Rows.Count new{id=jr.Field(table1PrimaryKey).Trim().ToLower()},
    (baseRow,joinRow)=>joinRow.DefaultIfEmpty()
    .选择(行=>新建)
    {
    flatRow=baseRow.ItemArray.Concat((row==null)?新对象[table1.Columns.Count]:
    row.ItemArray.ToArray()
    }))。选择多个(s=>s);
    var dataBaseTable1=table1.basenumerable();
    var groupDataT1toT2=dataBaseTable1.GroupJoin(table2.Select(),
    br=>新建{id=br.Field(table1PrimaryKey).Trim().ToLower()},
    jr=>新的{id=jr.Field(table2PrimaryKey).Trim().ToLower()},
    (baseRow,joinRow)=>joinRow.DefaultIfEmpty()
    .选择(行=>新建)
    {
    flatRow=(row==null)?新对象[table2.Columns.Count].ToArray().Concat(baseRow.ItemArray).ToArray():
    row.ItemArray.Concat(baseRow.ItemArray.ToArray())
    }))。选择多个(s=>s);
    //将两个组数据的并集获取到单个集合
    groupDataT2toT1=groupDataT2toT1.Union(groupDataT1toT2);
    //将分组数据加载到新创建的表中
    foreach(groupDataT2toT1中的var结果)
    {
    flatDataTable.LoadDataRow(result.flatRow,false);
    }
    //仅获取不同的行
    IEnumerable rows=flatDataTable.Select().Distinct(DataRowComparer.Default);
    //使用与flatDataTable相同的结构创建新的独立表
    DataTable distinctFlatDataTable=flatDataTable.Clone();
    distinctFlatDataTable.Rows.Clear();
    //将所有行推送到不同的表中。
    //注意:主键1和主键2将有两个不同的列。在分组行中,
    //主键1或主键2可以有空值。因此,将所有主键2值复制到
    //主键1仅当主键1值为空时,然后删除主键2。因此,最后
    //我们将只获得一个perimary密钥。请确保未删除的密钥必须存在于中
    foreach(数据行中的行)
    {
    if(string.IsNullOrEmpty(行[table1PrimaryKey].ToString())
    行[table1PrimaryKey]=行[table2PrimaryKey];
    if(string.IsNullOrEmpty(行[CaptureBusDateColumn].ToString())
    行[CaptureBusDateColumn]=\u businessDate;
    if(string.IsNullOrEmpty(行[CaptureUserIDColumn].ToString())
    行[CaptureUserIDColumn]=行[StatsUserIDColumn];
    distinctFlatDataTable.ImportRow(行);
    }
    //根据主键对表进行排序。
    DataTable sortedFinaltable=(来自distinctFlatDataTable.AsEnumerable()中的orderRow)
    orderby orderRow.Field(table1PrimaryKey)
    选择orderRow).CopyToDataTable();
    //删除主键2,因为我们已经将其复制到主键1
    sortedFinaltable.Columns.Remove(table2PrimaryKey);
    返回replacenalls(sortedFinaltable,“0”);
    }
    /// 
    ///用指定的字符串替换数据表中的所有空值
    /// 
    /// 
    /// 
    /// 
    专用数据表
    
    public DataTable FullOuterJoinDataTables(params DataTable[] datatables) // supports as many datatables as you need.
    {
        DataTable result = datatables.First().Clone();
    
        var commonColumns = result.Columns.OfType<DataColumn>();
    
        foreach (var dt in datatables.Skip(1))
        {
            commonColumns = commonColumns.Intersect(dt.Columns.OfType<DataColumn>(), new DataColumnComparer());
        }
    
        result.PrimaryKey = commonColumns.ToArray();
    
        foreach (var dt in datatables)
        {
            result.Merge(dt, false, MissingSchemaAction.AddWithKey);
        }
    
        return result;
    }
    
    /* also create this class */
    public class DataColumnComparer : IEqualityComparer<DataColumn>
    {
        public bool Equals(DataColumn x, DataColumn y) => x.Caption == y.Caption;       
    
        public int GetHashCode(DataColumn obj) => obj.Caption.GetHashCode();        
    }